mirror of https://github.com/sipwise/jitsi.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
788 lines
26 KiB
788 lines
26 KiB
/*
|
|
* 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.net.*;
|
|
import java.util.*;
|
|
|
|
import net.java.sip.communicator.service.protocol.event.*;
|
|
import net.java.sip.communicator.util.*;
|
|
|
|
/**
|
|
* Provides a default implementation for most of the
|
|
* <code>CallPeer</code> methods with the purpose of only leaving custom
|
|
* protocol development to clients using the PhoneUI service.
|
|
*
|
|
* @author Emil Ivov
|
|
* @author Lubomir Marinov
|
|
* @author Yana Stamcheva
|
|
*/
|
|
public abstract class AbstractCallPeer
|
|
extends PropertyChangeNotifier
|
|
implements CallPeer
|
|
{
|
|
private static final Logger logger
|
|
= Logger.getLogger(AbstractCallPeer.class);
|
|
|
|
/**
|
|
* The constant which describes an empty set of
|
|
* <code>ConferenceMember</code>s (and which can be used to reduce
|
|
* allocations).
|
|
*/
|
|
protected static final ConferenceMember[] NO_CONFERENCE_MEMBERS
|
|
= new ConferenceMember[0];
|
|
|
|
/**
|
|
* All the CallPeer listeners registered with this CallPeer.
|
|
*/
|
|
protected final List<CallPeerListener> callPeerListeners
|
|
= new ArrayList<CallPeerListener>();
|
|
|
|
/**
|
|
* All the CallPeerSecurityListener-s registered with this
|
|
* CallPeer.
|
|
*/
|
|
protected final List<CallPeerSecurityListener>
|
|
callPeerSecurityListeners
|
|
= new ArrayList<CallPeerSecurityListener>();
|
|
|
|
/**
|
|
* The <tt>StreamSoundLevelListener</tt>-s registered to get
|
|
* <tt>StreamSoundLevelEvent</tt>-s.
|
|
*/
|
|
private final List<StreamSoundLevelListener> streamSoundLevelListeners
|
|
= new ArrayList<StreamSoundLevelListener>();
|
|
|
|
/**
|
|
* The <tt>ConferenceMembersSoundLevelListener</tt>-s registered to get
|
|
* <tt>ConferenceMembersSoundLevelEvent</tt>-s.
|
|
*/
|
|
private final List<ConferenceMembersSoundLevelListener>
|
|
membersSoundLevelListeners
|
|
= new ArrayList<ConferenceMembersSoundLevelListener>();
|
|
|
|
/**
|
|
* The indicator which determines whether this peer is acting as a
|
|
* conference focus and thus may provide information about
|
|
* <code>ConferenceMember</code> such as {@link #getConferenceMembers()} and
|
|
* {@link #getConferenceMemberCount()}.
|
|
*/
|
|
private boolean conferenceFocus;
|
|
|
|
/**
|
|
* The list of <code>ConferenceMember</code>s currently known to and managed
|
|
* in a conference by this peer.
|
|
*/
|
|
private final List<ConferenceMember> conferenceMembers
|
|
= new ArrayList<ConferenceMember>();
|
|
|
|
/**
|
|
* The list of <code>CallPeerConferenceListener</code>s interested in
|
|
* and to be notified about changes in conference-related information such
|
|
* as this peer acting or not acting as a conference focus and
|
|
* conference membership details.
|
|
*/
|
|
protected final List<CallPeerConferenceListener>
|
|
callPeerConferenceListeners
|
|
= new ArrayList<CallPeerConferenceListener>();
|
|
|
|
/**
|
|
* The state of the call peer.
|
|
*/
|
|
private CallPeerState state = CallPeerState.UNKNOWN;
|
|
|
|
private long callDurationStartTime = CALL_DURATION_START_TIME_UNKNOWN;
|
|
|
|
private boolean isMute = false;
|
|
|
|
/**
|
|
* Registers the <tt>listener</tt> to the list of listeners that would be
|
|
* receiving CallPeerEvents
|
|
* @param listener a listener instance to register with this peer.
|
|
*/
|
|
public void addCallPeerListener(CallPeerListener listener)
|
|
{
|
|
if (listener == null)
|
|
return;
|
|
synchronized(callPeerListeners)
|
|
{
|
|
if (!callPeerListeners.contains(listener))
|
|
callPeerListeners.add(listener);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Unregisters the specified listener.
|
|
* @param listener the listener to unregister.
|
|
*/
|
|
public void removeCallPeerListener(CallPeerListener listener)
|
|
{
|
|
if (listener == null)
|
|
return;
|
|
synchronized(callPeerListeners)
|
|
{
|
|
callPeerListeners.remove(listener);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Registers the <tt>listener</tt> to the list of listeners that would be
|
|
* receiving CallPeerSecurityEvents
|
|
*
|
|
* @param listener a listener instance to register with this peer.
|
|
*/
|
|
public void addCallPeerSecurityListener(
|
|
CallPeerSecurityListener listener)
|
|
{
|
|
if (listener == null)
|
|
return;
|
|
synchronized(callPeerSecurityListeners)
|
|
{
|
|
if (!callPeerSecurityListeners.contains(listener))
|
|
callPeerSecurityListeners.add(listener);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Unregisters the specified listener.
|
|
*
|
|
* @param listener the listener to unregister.
|
|
*/
|
|
public void removeCallPeerSecurityListener(
|
|
CallPeerSecurityListener listener)
|
|
{
|
|
if (listener == null)
|
|
return;
|
|
synchronized(callPeerSecurityListeners)
|
|
{
|
|
callPeerSecurityListeners.remove(listener);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Constructs a <tt>CallPeerChangeEvent</tt> using this call
|
|
* peer as source, setting it to be of type <tt>eventType</tt> and
|
|
* the corresponding <tt>oldValue</tt> and <tt>newValue</tt>,
|
|
*
|
|
* @param eventType the type of the event to create and dispatch.
|
|
* @param oldValue the value of the source property before it changed.
|
|
* @param newValue the current value of the source property.
|
|
*/
|
|
protected void fireCallPeerChangeEvent(String eventType,
|
|
Object oldValue,
|
|
Object newValue)
|
|
{
|
|
this.fireCallPeerChangeEvent( eventType, oldValue, newValue, null);
|
|
}
|
|
|
|
|
|
/**
|
|
* Constructs a <tt>CallPeerChangeEvent</tt> using this call
|
|
* peer as source, setting it to be of type <tt>eventType</tt> and
|
|
* the corresponding <tt>oldValue</tt> and <tt>newValue</tt>,
|
|
*
|
|
* @param eventType the type of the event to create and dispatch.
|
|
* @param oldValue the value of the source property before it changed.
|
|
* @param newValue the current value of the source property.
|
|
* @param reason a string that could be set to contain a human readable
|
|
* explanation for the transition (particularly handy when moving into a
|
|
* FAILED state).
|
|
*/
|
|
protected void fireCallPeerChangeEvent(String eventType,
|
|
Object oldValue,
|
|
Object newValue,
|
|
String reason)
|
|
{
|
|
CallPeerChangeEvent evt = new CallPeerChangeEvent(
|
|
this, eventType, oldValue, newValue, reason);
|
|
|
|
logger.debug("Dispatching a CallPeerChangeEvent event to "
|
|
+ callPeerListeners.size()
|
|
+" listeners. event is: " + evt.toString());
|
|
|
|
Iterator<CallPeerListener> listeners = null;
|
|
synchronized (callPeerListeners)
|
|
{
|
|
listeners = new ArrayList<CallPeerListener>(
|
|
callPeerListeners).iterator();
|
|
}
|
|
|
|
while (listeners.hasNext())
|
|
{
|
|
CallPeerListener listener = listeners.next();
|
|
|
|
if(eventType.equals(CallPeerChangeEvent
|
|
.CALL_PEER_ADDRESS_CHANGE))
|
|
{
|
|
listener.peerAddressChanged(evt);
|
|
} else if(eventType.equals(CallPeerChangeEvent
|
|
.CALL_PEER_DISPLAY_NAME_CHANGE))
|
|
{
|
|
listener.peerDisplayNameChanged(evt);
|
|
} else if(eventType.equals(CallPeerChangeEvent
|
|
.CALL_PEER_IMAGE_CHANGE))
|
|
{
|
|
listener.peerImageChanged(evt);
|
|
} else if(eventType.equals(CallPeerChangeEvent
|
|
.CALL_PEER_STATE_CHANGE))
|
|
{
|
|
listener.peerStateChanged(evt);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Constructs a <tt>CallPeerSecurityStatusEvent</tt> using this call
|
|
* peer as source, setting it to be of type <tt>eventType</tt> and
|
|
* the corresponding <tt>oldValue</tt> and <tt>newValue</tt>
|
|
*
|
|
* @param sessionType the type of the session - audio or video
|
|
* @param cipher the cipher associated with the event.
|
|
* @param securityString the security string associated with this event.
|
|
* @param isVerified <tt>true</tt> if the session is verified and
|
|
* <tt>false</tt> otherwise.
|
|
*/
|
|
protected void fireCallPeerSecurityOnEvent(int sessionType, String cipher,
|
|
String securityString, boolean isVerified)
|
|
{
|
|
CallPeerSecurityOnEvent evt
|
|
= new CallPeerSecurityOnEvent(
|
|
this, sessionType, cipher, securityString, isVerified);
|
|
|
|
logger.debug("Dispatching a CallPeerSecurityStatusEvent event to "
|
|
+ callPeerSecurityListeners.size()
|
|
+" listeners. event is: " + evt.toString());
|
|
|
|
Iterator<CallPeerSecurityListener> listeners = null;
|
|
synchronized (callPeerSecurityListeners)
|
|
{
|
|
listeners = new ArrayList<CallPeerSecurityListener>(
|
|
callPeerSecurityListeners).iterator();
|
|
}
|
|
|
|
while (listeners.hasNext())
|
|
{
|
|
CallPeerSecurityListener listener = listeners.next();
|
|
|
|
listener.securityOn(evt);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Constructs a <tt>CallPeerSecurityStatusEvent</tt> using this call
|
|
* peer as source, setting it to be of type <tt>eventType</tt> and
|
|
* the corresponding <tt>oldValue</tt> and <tt>newValue</tt>,
|
|
*
|
|
* @param sessionType the type of the session - audio or video
|
|
*/
|
|
protected void fireCallPeerSecurityOffEvent(int sessionType)
|
|
{
|
|
CallPeerSecurityOffEvent event
|
|
= new CallPeerSecurityOffEvent( this, sessionType);
|
|
|
|
logger.debug(
|
|
"Dispatching a CallPeerSecurityAuthenticationEvent event to "
|
|
+ callPeerSecurityListeners.size()
|
|
+" listeners. event is: " + event.toString());
|
|
|
|
Iterator<CallPeerSecurityListener> listeners = null;
|
|
synchronized (callPeerSecurityListeners)
|
|
{
|
|
listeners = new ArrayList<CallPeerSecurityListener>(
|
|
callPeerSecurityListeners).iterator();
|
|
}
|
|
|
|
while (listeners.hasNext())
|
|
{
|
|
CallPeerSecurityListener listener = listeners.next();
|
|
|
|
listener.securityOff(event);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Constructs a <tt>CallPeerSecurityStatusEvent</tt> using this call
|
|
* peer as source, setting it to be of type <tt>eventType</tt> and
|
|
* the corresponding <tt>oldValue</tt> and <tt>newValue</tt>,
|
|
*
|
|
* @param messageType the type of the message
|
|
* @param i18nMessage message
|
|
* @param severity severity level
|
|
*/
|
|
protected void fireCallPeerSecurityMessageEvent(
|
|
String messageType,
|
|
String i18nMessage,
|
|
int severity)
|
|
{
|
|
CallPeerSecurityMessageEvent evt
|
|
= new CallPeerSecurityMessageEvent( this,
|
|
messageType,
|
|
i18nMessage,
|
|
severity);
|
|
|
|
logger.debug("Dispatching a CallPeerSecurityFailedEvent event to "
|
|
+ callPeerSecurityListeners.size()
|
|
+" listeners. event is: " + evt.toString());
|
|
|
|
Iterator<CallPeerSecurityListener> listeners = null;
|
|
synchronized (callPeerSecurityListeners)
|
|
{
|
|
listeners = new ArrayList<CallPeerSecurityListener>(
|
|
callPeerSecurityListeners).iterator();
|
|
}
|
|
|
|
while (listeners.hasNext())
|
|
{
|
|
CallPeerSecurityListener listener = listeners.next();
|
|
|
|
listener.securityMessageRecieved(evt);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a string representation of the peer in the form of
|
|
* <br/>
|
|
* Display Name <address>;status=CallPeerStatus
|
|
* @return a string representation of the peer and its state.
|
|
*/
|
|
public String toString()
|
|
{
|
|
return getDisplayName() + " <" + getAddress()
|
|
+ ">;status=" + getState().getStateString();
|
|
}
|
|
|
|
/**
|
|
* Returns a URL pointing ta a location with call control information for
|
|
* this peer or <tt>null</tt> if no such URL is available for this
|
|
* call peer.
|
|
*
|
|
* @return a URL link to a location with call information or a call control
|
|
* web interface related to this peer or <tt>null</tt> if no such URL
|
|
* is available.
|
|
*/
|
|
public URL getCallInfoURL()
|
|
{
|
|
//if signaling protocols (such as SIP) know where to get this URL from
|
|
//they should override this method
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Returns an object representing the current state of that peer.
|
|
*
|
|
* @return a CallPeerState instance representing the peer's state.
|
|
*/
|
|
public CallPeerState getState()
|
|
{
|
|
return state;
|
|
}
|
|
|
|
/**
|
|
* Causes this CallPeer to enter the specified state. The method also
|
|
* sets the currentStateStartDate field and fires a
|
|
* CallPeerChangeEvent.
|
|
*
|
|
* @param newState the state this call peer should enter.
|
|
* @param reason a string that could be set to contain a human readable
|
|
* explanation for the transition (particularly handy when moving into a
|
|
* FAILED state).
|
|
*/
|
|
public void setState(CallPeerState newState, String reason)
|
|
{
|
|
CallPeerState oldState = getState();
|
|
|
|
if(oldState == newState)
|
|
return;
|
|
|
|
this.state = newState;
|
|
|
|
if (CallPeerState.CONNECTED.equals(newState)
|
|
&& !CallPeerState.isOnHold(oldState))
|
|
{
|
|
callDurationStartTime = System.currentTimeMillis();
|
|
}
|
|
|
|
fireCallPeerChangeEvent(
|
|
CallPeerChangeEvent.CALL_PEER_STATE_CHANGE,
|
|
oldState,
|
|
newState);
|
|
}
|
|
|
|
/**
|
|
* Causes this CallPeer to enter the specified state. The method also
|
|
* sets the currentStateStartDate field and fires a
|
|
* CallPeerChangeEvent.
|
|
*
|
|
* @param newState the state this call peer should enter.
|
|
*/
|
|
public void setState(CallPeerState newState)
|
|
{
|
|
setState(newState, null);
|
|
}
|
|
|
|
/**
|
|
* Gets the time at which this <code>CallPeer</code> transitioned
|
|
* into a state (likely {@link CallPeerState#CONNECTED}) marking the
|
|
* start of the duration of the participation in a <code>Call</code>.
|
|
*
|
|
* @return the time at which this <code>CallPeer</code> transitioned
|
|
* into a state marking the start of the duration of the
|
|
* participation in a <code>Call</code> or
|
|
* {@link CallPeer#CALL_DURATION_START_TIME_UNKNOWN} if such
|
|
* a transition has not been performed
|
|
*/
|
|
public long getCallDurationStartTime()
|
|
{
|
|
return callDurationStartTime;
|
|
}
|
|
|
|
/**
|
|
* Determines whether the audio stream (if any) being sent to this
|
|
* peer is mute.
|
|
* <p>
|
|
* The default implementation returns <tt>false</tt>.
|
|
* </p>
|
|
*
|
|
* @return <tt>true</tt> if an audio stream is being sent to this
|
|
* peer and it is currently mute; <tt>false</tt>, otherwise
|
|
*/
|
|
public boolean isMute()
|
|
{
|
|
return isMute;
|
|
}
|
|
|
|
/**
|
|
* Sets the mute property for this call peer.
|
|
*
|
|
* @param newMuteValue the new value of the mute property for this call peer
|
|
*/
|
|
public void setMute(boolean newMuteValue)
|
|
{
|
|
this.isMute = newMuteValue;
|
|
firePropertyChange(MUTE_PROPERTY_NAME, isMute, newMuteValue);
|
|
}
|
|
|
|
/**
|
|
* Determines whether this call peer is currently a conference focus.
|
|
*
|
|
* @return <tt>true</tt> if this peer is a conference focus and
|
|
* <tt>false</tt> otherwise.
|
|
*/
|
|
public boolean isConferenceFocus()
|
|
{
|
|
return conferenceFocus;
|
|
}
|
|
|
|
/**
|
|
* Specifies whether this peer is a conference focus.
|
|
*
|
|
* @param conferenceFocus <tt>true</tt> if this peer is to become a
|
|
* conference focus and <tt>false</tt> otherwise.
|
|
*/
|
|
public void setConferenceFocus(boolean conferenceFocus)
|
|
{
|
|
if (this.conferenceFocus != conferenceFocus)
|
|
{
|
|
this.conferenceFocus = conferenceFocus;
|
|
|
|
fireCallPeerConferenceEvent( new CallPeerConferenceEvent(
|
|
this, CallPeerConferenceEvent.CONFERENCE_FOCUS_CHANGED));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Implements <tt>CallPeer#getConferenceMembers()</tt>. In order to reduce
|
|
* allocations, returns #NO_CONFERENCE_MEMBERS if #conferenceMembers
|
|
* contains no ConferenceMember instances.
|
|
* @return an array of the conference members
|
|
*/
|
|
public ConferenceMember[] getConferenceMembers()
|
|
{
|
|
ConferenceMember[] conferenceMembers;
|
|
|
|
synchronized (this.conferenceMembers)
|
|
{
|
|
int conferenceMemberCount = this.conferenceMembers.size();
|
|
|
|
if (conferenceMemberCount <= 0)
|
|
conferenceMembers = NO_CONFERENCE_MEMBERS;
|
|
else
|
|
conferenceMembers
|
|
= this.conferenceMembers
|
|
.toArray(
|
|
new ConferenceMember[conferenceMemberCount]);
|
|
}
|
|
return conferenceMembers;
|
|
}
|
|
|
|
/**
|
|
* Returns the count of the members contained in this peer.
|
|
* <p>
|
|
* Implements <tt>CallPeer#getConferenceMemberCount()</tt>.
|
|
* @return the count of the members contained in this peer
|
|
*/
|
|
public int getConferenceMemberCount()
|
|
{
|
|
return conferenceMembers.size();
|
|
}
|
|
|
|
/**
|
|
* Adds a specific <code>ConferenceMember</code> to the list of
|
|
* <code>ConferenceMember</code>s reported by this peer through
|
|
* {@link #getConferenceMembers()} and {@link #getConferenceMemberCount()}
|
|
* and fires
|
|
* <code>CallPeerConferenceEvent#CONFERENCE_MEMBER_ADDED</code> to
|
|
* the currently registered <code>CallPeerConferenceListener</code>s.
|
|
*
|
|
* @param conferenceMember
|
|
* a <code>ConferenceMember</code> to be added to the list of
|
|
* <code>ConferenceMember</code> reported by this peer. If
|
|
* the specified <code>ConferenceMember</code> is already
|
|
* contained in the list, it is not added again and no event is
|
|
* fired.
|
|
*/
|
|
public void addConferenceMember(ConferenceMember conferenceMember)
|
|
{
|
|
if (conferenceMember == null)
|
|
throw new NullPointerException("conferenceMember");
|
|
synchronized (conferenceMembers)
|
|
{
|
|
if (conferenceMembers.contains(conferenceMember))
|
|
return;
|
|
conferenceMembers.add(conferenceMember);
|
|
}
|
|
fireCallPeerConferenceEvent(
|
|
new CallPeerConferenceEvent(
|
|
this,
|
|
CallPeerConferenceEvent.CONFERENCE_MEMBER_ADDED,
|
|
conferenceMember));
|
|
}
|
|
|
|
/**
|
|
* Removes a specific <code>ConferenceMember</code> from the list of
|
|
* <code>ConferenceMember</code>s reported by this peer through
|
|
* {@link #getConferenceMembers()} and {@link #getConferenceMemberCount()}
|
|
* if it is contained and fires
|
|
* <code>CallPeerConferenceEvent#CONFERENCE_MEMBER_REMOVED</code> to
|
|
* the currently registered <code>CallPeerConferenceListener</code>s.
|
|
*
|
|
* @param conferenceMember
|
|
* a <code>ConferenceMember</code> to be removed from the list of
|
|
* <code>ConferenceMember</code> reported by this peer. If
|
|
* the specified <code>ConferenceMember</code> is no contained in
|
|
* the list, no event is fired.
|
|
*/
|
|
public void removeConferenceMember(ConferenceMember conferenceMember)
|
|
{
|
|
if (conferenceMember == null)
|
|
throw new NullPointerException("conferenceMember");
|
|
synchronized (conferenceMembers)
|
|
{
|
|
if (!conferenceMembers.remove(conferenceMember))
|
|
return;
|
|
}
|
|
fireCallPeerConferenceEvent(
|
|
new CallPeerConferenceEvent(
|
|
this,
|
|
CallPeerConferenceEvent.CONFERENCE_MEMBER_REMOVED,
|
|
conferenceMember));
|
|
}
|
|
|
|
/**
|
|
* ImplementsCallPeer#addCallPeerConferenceListener(
|
|
* CallPeerConferenceListener). In the fashion of the addition of the
|
|
* other listeners, does not throw an exception on attempting to add a null
|
|
* listeners and just ignores the call.
|
|
* @param listener the <tt>CallPeerConferenceListener</tt> to add
|
|
*/
|
|
public void addCallPeerConferenceListener(
|
|
CallPeerConferenceListener listener)
|
|
{
|
|
if (listener != null)
|
|
synchronized (callPeerConferenceListeners)
|
|
{
|
|
if (!callPeerConferenceListeners.contains(listener))
|
|
callPeerConferenceListeners.add(listener);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Implements CallPeer#removeCallPeerConferenceListener(
|
|
* CallPeerConferenceListener).
|
|
* @param listener the <tt>CallPeerConferenceListener</tt> to remove
|
|
*/
|
|
public void removeCallPeerConferenceListener(
|
|
CallPeerConferenceListener listener)
|
|
{
|
|
if (listener != null)
|
|
synchronized (callPeerConferenceListeners)
|
|
{
|
|
callPeerConferenceListeners.remove(listener);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds a specific <tt>StreamSoundLevelListener</tt> to the list of
|
|
* listeners interested in and notified about changes in stream sound level
|
|
* related information.
|
|
*
|
|
* @param listener the <tt>StreamSoundLevelListener</tt> to add
|
|
*/
|
|
public void addStreamSoundLevelListener(StreamSoundLevelListener listener)
|
|
{
|
|
if (listener != null)
|
|
synchronized (streamSoundLevelListeners)
|
|
{
|
|
streamSoundLevelListeners.add(listener);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Removes a specific <tt>StreamSoundLevelListener</tt> of the list of
|
|
* listeners interested in and notified about changes in stream sound level
|
|
* related information.
|
|
*
|
|
* @param listener the <tt>StreamSoundLevelListener</tt> to remove
|
|
*/
|
|
public void removeStreamSoundLevelListener(
|
|
StreamSoundLevelListener listener)
|
|
{
|
|
if (listener != null)
|
|
synchronized (streamSoundLevelListeners)
|
|
{
|
|
streamSoundLevelListeners.remove(listener);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds a specific <tt>ConferenceMembersSoundLevelListener</tt> to the list
|
|
* of listeners interested in and notified about changes in conference
|
|
* members sound level.
|
|
*
|
|
* @param listener the <tt>ConferenceMembersSoundLevelListener</tt> to add
|
|
*/
|
|
public void addConferenceMembersSoundLevelListener(
|
|
ConferenceMembersSoundLevelListener listener)
|
|
{
|
|
if (listener != null)
|
|
synchronized (membersSoundLevelListeners)
|
|
{
|
|
membersSoundLevelListeners.add(listener);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Removes a specific <tt>ConferenceMembersSoundLevelListener</tt> of the
|
|
* list of listeners interested in and notified about changes in conference
|
|
* members sound level.
|
|
*
|
|
* @param listener the <tt>ConferenceMembersSoundLevelListener</tt> to
|
|
* remove
|
|
*/
|
|
public void removeConferenceMembersSoundLevelListener(
|
|
ConferenceMembersSoundLevelListener listener)
|
|
{
|
|
if (listener != null)
|
|
synchronized (membersSoundLevelListeners)
|
|
{
|
|
membersSoundLevelListeners.remove(listener);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fires a specific <code>CallPeerConferenceEvent</code> to the
|
|
* <code>CallPeerConferenceListener</code>s interested in changes in
|
|
* the conference-related information provided by this peer.
|
|
*
|
|
* @param conferenceEvent
|
|
* a <code>CallPeerConferenceEvent</code> to be fired and
|
|
* carrying the event data
|
|
*/
|
|
protected void fireCallPeerConferenceEvent(
|
|
CallPeerConferenceEvent conferenceEvent)
|
|
{
|
|
CallPeerConferenceListener[] listeners;
|
|
|
|
synchronized (callPeerConferenceListeners)
|
|
{
|
|
listeners
|
|
= callPeerConferenceListeners
|
|
.toArray(
|
|
new CallPeerConferenceListener[
|
|
callPeerConferenceListeners.size()]);
|
|
}
|
|
|
|
int eventID = conferenceEvent.getEventID();
|
|
|
|
for (CallPeerConferenceListener listener : listeners)
|
|
switch (eventID)
|
|
{
|
|
case CallPeerConferenceEvent.CONFERENCE_FOCUS_CHANGED:
|
|
listener.conferenceFocusChanged(conferenceEvent);
|
|
break;
|
|
case CallPeerConferenceEvent.CONFERENCE_MEMBER_ADDED:
|
|
listener.conferenceMemberAdded(conferenceEvent);
|
|
break;
|
|
case CallPeerConferenceEvent.CONFERENCE_MEMBER_REMOVED:
|
|
listener.conferenceMemberRemoved(conferenceEvent);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fires a <tt>StreamSoundLevelEvent</tt> and notifies all registered
|
|
* listeners.
|
|
*
|
|
* @param level the new sound level
|
|
*/
|
|
public void fireStreamSoundLevelEvent(int level)
|
|
{
|
|
StreamSoundLevelEvent event
|
|
= new StreamSoundLevelEvent(this, level);
|
|
|
|
StreamSoundLevelListener[] listeners;
|
|
|
|
synchronized(streamSoundLevelListeners)
|
|
{
|
|
listeners = streamSoundLevelListeners.toArray(
|
|
new StreamSoundLevelListener[streamSoundLevelListeners.size()]);
|
|
}
|
|
|
|
for (StreamSoundLevelListener listener : listeners)
|
|
{
|
|
listener.streamSoundLevelChanged(event);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fires a <tt>ConferenceMembersSoundLevelListener</tt> and notifies all
|
|
* registered listeners.
|
|
*
|
|
* @param levels the new conference members sound levels
|
|
*/
|
|
public void fireConferenceMembersSoundLevelEvent(
|
|
Map<ConferenceMember, Integer> levels)
|
|
{
|
|
ConferenceMembersSoundLevelEvent event
|
|
= new ConferenceMembersSoundLevelEvent(this, levels);
|
|
|
|
ConferenceMembersSoundLevelListener[] listeners;
|
|
|
|
synchronized(membersSoundLevelListeners)
|
|
{
|
|
listeners = membersSoundLevelListeners.toArray(
|
|
new ConferenceMembersSoundLevelListener
|
|
[membersSoundLevelListeners.size()]);
|
|
}
|
|
|
|
for (ConferenceMembersSoundLevelListener listener : listeners)
|
|
{
|
|
listener.membersSoundLevelChanged(event);
|
|
}
|
|
}
|
|
}
|