Attempt to support the creation of conference calls and the display of conference-related information to the peers participating in the conference. Represents work in progress because the media is still not aware of the conferences.

cusax-fix
Lyubomir Marinov 16 years ago
parent ea8dc10d6a
commit d89b89d290

@ -119,7 +119,7 @@ service.gui.INVITATION=Текст на поканата
service.gui.INVITATION_RECEIVED=Получена е покана
service.gui.INVITATION_RECEIVED_MSG={0} ви кани да влезете в стая {1}. Можете да приемете, откажете или да пренебрегнете тази покана.
service.gui.INVITE=&Покана
service.gui.INVITE_CONTACT_MSG=Моля въведете името на потребителя който бихте желали да поканите. Ако желаете можете да въведете и обяснение към поканата.
service.gui.INVITE_CONTACT_MSG=Моля въведете името на потребителя, който бихте желали да поканите. Ако желаете, можете да въведете и обяснение към поканата.
service.gui.INVITE_CONTACT_TO_CHAT=Покани контакт на чат
service.gui.JOIN=&Влез
service.gui.JOIN_AS=В&лез като

@ -390,6 +390,7 @@ public CreateConferenceCallThread(
this.protocolProvider = protocolProvider;
}
@Override
public void run()
{
OperationSetTelephonyConferencing confOpSet
@ -405,19 +406,31 @@ public void run()
if (confOpSet == null)
return;
Throwable exception = null;
try
{
confOpSet.createConfCall(callees);
}
catch (OperationNotSupportedException e)
catch (OperationFailedException ofe)
{
exception = ofe;
}
catch (OperationNotSupportedException onse)
{
exception = onse;
}
if (exception != null)
{
logger.error("Failed to create conference call. " + e);
logger.error("Failed to create conference call. " + exception);
new ErrorDialog(null,
GuiActivator.getResources()
.getI18NString("service.gui.ERROR"),
e.getMessage(),
ErrorDialog.ERROR).showDialog();
new ErrorDialog(
null,
GuiActivator
.getResources().getI18NString("service.gui.ERROR"),
exception.getMessage(),
ErrorDialog.ERROR)
.showDialog();
}
}
}
@ -438,6 +451,7 @@ public InviteToConferenceCallThread(String[] callees, Call call)
this.call = call;
}
@Override
public void run()
{
OperationSetTelephonyConferencing confOpSet
@ -456,19 +470,33 @@ public void run()
for (String callee : callees)
{
Throwable exception = null;
try
{
confOpSet.inviteCalleeToCall(callee, call);
}
catch (OperationNotSupportedException e)
catch (OperationFailedException ofe)
{
logger.error("Failed to invite callee: " + callee, e);
new ErrorDialog(null,
GuiActivator.getResources()
.getI18NString("service.gui.ERROR"),
e.getMessage(),
ErrorDialog.ERROR).showDialog();
exception = ofe;
}
catch (OperationNotSupportedException onse)
{
exception = onse;
}
if (exception != null)
{
logger
.error("Failed to invite callee: " + callee, exception);
new ErrorDialog(
null,
GuiActivator
.getResources()
.getI18NString("service.gui.ERROR"),
exception.getMessage(),
ErrorDialog.ERROR)
.showDialog();
}
}
}

@ -162,15 +162,11 @@ private void registerMenuItems()
GuiActivator.getResources().getI18NString(
"service.gui.CREATE_CONFERENCE_CALL") + " (coming soon)");
// Disables the conference menu item until the work on this feature is
// completed and fully tested.
conferenceMenuItem.setEnabled(false);
this.add(conferenceMenuItem);
conferenceMenuItem.setMnemonic(GuiActivator.getResources()
.getI18nMnemonic("service.gui.CREATE_CONFERENCE_CALL"));
conferenceMenuItem.setName("conference");
conferenceMenuItem.addActionListener(this);
this.add(conferenceMenuItem);
}
private boolean registerConfigMenuItemMacOSX()

@ -1094,6 +1094,30 @@ private StreamConnector createStreamConnector()
return connector;
}
/**
* Gets the <tt>MediaStream</tt> of this <tt>CallPeerMediaHandler</tt> which
* is of a specific <tt>MediaType</tt>. If this instance doesn't have such a
* <tt>MediaStream</tt>, returns <tt>null</tt>
*
* @param mediaType the <tt>MediaType</tt> of the <tt>MediaStream</tt> to
* retrieve
* @return the <tt>MediaStream</tt> of this <tt>CallPeerMediaHandler</tt>
* which is of the specified <tt>mediaType</tt> if this instance has such a
* <tt>MediaStream</tt>; otherwise, <tt>null</tt>
*/
MediaStream getStream(MediaType mediaType)
{
switch (mediaType)
{
case AUDIO:
return audioStream;
case VIDEO:
return videoStream;
default:
throw new IllegalArgumentException("mediaType");
}
}
/**
* Returns the <tt>StreamConnector</tt> instance that this media handler
* should use for streams of the specified <tt>mediaType</tt>. The method

@ -24,6 +24,7 @@
* Our SIP implementation of the default CallPeer;
*
* @author Emil Ivov
* @author Lubomir Marinov
*/
public class CallPeerSipImpl
extends AbstractCallPeer
@ -80,12 +81,6 @@ public class CallPeerSipImpl
*/
private InetSocketAddress transportAddress = null;
/**
* A reference to the <tt>SipMessageFactory</tt> instance that we should
* use when creating requests.
*/
private final SipMessageFactory messageFactory;
/**
* The media handler class handles all media management for a single
* <tt>CallPeer</tt>. This includes initializing and configuring streams,
@ -101,6 +96,19 @@ public class CallPeerSipImpl
*/
private PropertyChangeListener mediaHandlerPropertyChangeListener;
/**
* A reference to the <tt>SipMessageFactory</tt> instance that we should
* use when creating requests.
*/
private final SipMessageFactory messageFactory;
/**
* The <tt>List</tt> of <tt>MethodProcessorListener</tt>s interested in how
* this <tt>CallPeer</tt> processes SIP signaling.
*/
private final List<MethodProcessorListener> methodProcessorListeners
= new LinkedList<MethodProcessorListener>();
/**
* The <tt>List</tt> of <tt>PropertyChangeListener</tt>s listening to this
* <tt>CallPeer</tt> for changes in the values of its properties related to
@ -492,6 +500,13 @@ public void processReInvite(ServerTransaction serverTransaction)
{
response = messageFactory.createResponse(Response.OK, invite);
/*
* If the local peer represented by the Call of this CallPeer is
* acting as a conference focus, it must indicate it in its Contact
* header.
*/
reflectConferenceFocus(response);
String sdpAnswer;
if(sdpOffer != null)
sdpAnswer = getMediaHandler().processOffer( sdpOffer );
@ -517,6 +532,8 @@ public void processReInvite(ServerTransaction serverTransaction)
}
reevalRemoteHoldStatus();
fireRequestProcessed(invite, response);
}
/**
@ -878,6 +895,8 @@ public void processInviteOK(ClientTransaction clientTransaction,
// change status
if (!CallPeerState.isOnHold(getState()))
setState(CallPeerState.CONNECTED);
fireResponseProcessed(ok, null);
}
/**
@ -1098,11 +1117,18 @@ public synchronized void answer()
}
ServerTransaction serverTransaction = (ServerTransaction) transaction;
Request invite = serverTransaction.getRequest();
Response ok = null;
try
{
ok = messageFactory.createResponse(
Response.OK, serverTransaction.getRequest());
ok = messageFactory.createResponse(Response.OK, invite);
/*
* If the local peer represented by the Call of this CallPeer is
* acting as a conference focus, it must indicate it in its Contact
* header.
*/
reflectConferenceFocus(ok);
}
catch (ParseException ex)
{
@ -1137,7 +1163,6 @@ public synchronized void answer()
// extract the SDP description.
// beware: SDP description may be in ACKs so it could be that there's
// nothing here - bug report Laurent Michel
Request invite = getLatestInviteTransaction().getRequest();
ContentLengthHeader cl = invite.getContentLength();
if (cl != null && cl.getContentLength() > 0)
{
@ -1182,6 +1207,8 @@ public synchronized void answer()
"Failed to send an OK response to an INVITE request",
OperationFailedException.NETWORK_FAILURE, ex, logger);
}
fireRequestProcessed(invite, ok);
}
/**
@ -1214,9 +1241,21 @@ public void putOnHold(boolean onHold)
reevalLocalHoldStatus();
}
/**
* Sends a reINVITE request to this <tt>CallPeer</tt> within its current
* <tt>Dialog</tt>.
*
* @throws OperationFailedException if sending the reINVITE request fails
*/
void sendReInvite()
throws OperationFailedException
{
sendReInvite(getMediaHandler().createOffer());
}
/**
* Sends a reINVITE request with a specific <tt>sdpOffer</tt> (description)
* within the current <tt>Dialog</tt> with a the call peer represented by
* within the current <tt>Dialog</tt> with the call peer represented by
* this instance.
*
* @param sdpOffer the offer that we'd like to use for the newly created
@ -1233,8 +1272,16 @@ private void sendReInvite(String sdpOffer)
try
{
// Content-Type
invite.setContent(sdpOffer, getProtocolProvider().getHeaderFactory()
.createContentTypeHeader("application", "sdp"));
/*
* If the local peer represented by the Call of this CallPeer is
* acting as a conference focus, it must indicate it in its Contact
* header.
*/
reflectConferenceFocus(invite);
}
catch (ParseException ex)
{
@ -1260,17 +1307,27 @@ private void sendReInvite(String sdpOffer)
public void invite()
throws OperationFailedException
{
ClientTransaction inviteTran;
try
{
inviteTran = (ClientTransaction)getLatestInviteTransaction();
ClientTransaction inviteTran
= (ClientTransaction) getLatestInviteTransaction();
Request invite = inviteTran.getRequest();
ContentTypeHeader contentTypeHeader = getProtocolProvider()
.getHeaderFactory().createContentTypeHeader(
"application", "sdp");
// Content-Type
ContentTypeHeader contentTypeHeader
= getProtocolProvider()
.getHeaderFactory()
.createContentTypeHeader("application", "sdp");
inviteTran.getRequest().setContent(getMediaHandler().createOffer(),
contentTypeHeader);
invite
.setContent(getMediaHandler().createOffer(), contentTypeHeader);
/*
* If the local peer represented by the Call of this CallPeer is
* acting as a conference focus, it must indicate it in its Contact
* header.
*/
reflectConferenceFocus(invite);
inviteTran.sendRequest();
if (logger.isDebugEnabled())
@ -1284,6 +1341,33 @@ public void invite()
}
}
/**
* Reflects the value of the <tt>conferenceFocus</tt> property of the
* <tt>Call</tt> of this <tt>CallPeer</tt> in the specified SIP
* <tt>Message</tt>.
*
* @param message the SIP <tt>Message</tt> in which the value of the
* <tt>conferenceFocus</tt> property of the <tt>Call</tt> of this
* <tt>CallPeer</tt> is to be reflected
* @throws ParseException if modifying the specified SIP <tt>Message</tt> to
* reflect the <tt>conferenceFocus</tt> property of the <tt>Call</tt> of
* this <tt>CallPeer</tt> fails
*/
private void reflectConferenceFocus(javax.sip.message.Message message)
throws ParseException
{
ContactHeader contactHeader
= (ContactHeader) message.getHeader(ContactHeader.NAME);
if (contactHeader != null)
{
if (getCall().isConferenceFocus())
contactHeader.setParameter("isfocus", "");
else
contactHeader.removeParameter("isfocus");
}
}
/**
* Modifies the local media setup to reflect the requested setting for the
* streaming of the local video and then re-invites the peer represented by
@ -1430,6 +1514,97 @@ public void removeVideoPropertyChangeListener(
}
}
/**
* Registers a specific <tt>MethodProcessorListener</tt> with this
* <tt>CallPeer</tt> so that it gets notified by this instance about the
* processing of SIP signaling. If the specified <tt>listener</tt> is
* already registered with this instance, does nothing
*
* @param listener the <tt>MethodProcessorListener</tt> to be registered
* with this <tt>CallPeer</tt> so that it gets notified by this instance
* about the processing of SIP signaling
*/
void addMethodProcessorListener(MethodProcessorListener listener)
{
if (listener == null)
throw new NullPointerException("listener");
synchronized (methodProcessorListeners)
{
if (!methodProcessorListeners.contains(listener))
methodProcessorListeners.add(listener);
}
}
/**
* Notifies the <tt>MethodProcessorListener</tt>s registered with this
* <tt>CallPeer</tt> that it has processed a specific SIP <tt>Request</tt>
* by sending a specific SIP <tt>Response</tt>.
*
* @param request the SIP <tt>Request</tt> processed by this
* <tt>CallPeer</tt>
* @param response the SIP <tt>Response</tt> this <tt>CallPeer</tt> sent as
* part of its processing of the specified <tt>request</tt>
*/
protected void fireRequestProcessed(Request request, Response response)
{
Iterable<MethodProcessorListener> listeners;
synchronized (methodProcessorListeners)
{
listeners
= new LinkedList<MethodProcessorListener>(
methodProcessorListeners);
}
for (MethodProcessorListener listener : listeners)
listener.requestProcessed(this, request, response);
}
/**
* Notifies the <tt>MethodProcessorListener</tt>s registered with this
* <tt>CallPeer</tt> that it has processed a specific SIP <tt>Response</tt>
* by sending a specific SIP <tt>Request</tt>.
*
* @param response the SIP <tt>Response</tt> processed by this
* <tt>CallPeer</tt>
* @param request the SIP <tt>Request</tt> this <tt>CallPeer</tt> sent as
* part of its processing of the specified <tt>response</tt>
*/
protected void fireResponseProcessed(Response response, Request request)
{
Iterable<MethodProcessorListener> listeners;
synchronized (methodProcessorListeners)
{
listeners
= new LinkedList<MethodProcessorListener>(
methodProcessorListeners);
}
for (MethodProcessorListener listener : listeners)
listener.responseProcessed(this, response, request);
}
/**
* Unregisters a specific <tt>MethodProcessorListener</tt> from this
* <tt>CallPeer</tt> so that it no longer gets notified by this instance
* about the processing of SIP signaling. If the specified <tt>listener</tt>
* is not registered with this instance, does nothing.
*
* @param listener the <tt>MethodProcessorListener</tt> to be unregistered
* from this <tt>CallPeer</tt> so that it no longer gets notified by this
* instance about the processing of SIP signaling
*/
void removeMethodProcessorListener(MethodProcessorListener listener)
{
if (listener != null)
synchronized (methodProcessorListeners)
{
methodProcessorListeners.remove(listener);
}
}
/**
* Updates this call so that it would record a new transaction and dialog
* that have been recreated because of a re-authentication.

@ -36,6 +36,19 @@ public class CallSipImpl
private final List<CallPeerSipImpl> callPeers =
new Vector<CallPeerSipImpl>();
/**
* The indicator which determines whether the local peer represented by this
* <tt>Call</tt> is acting as a conference focus and is thus specifying the
* &quot;isfocus&quot; parameter in the Contact headers of its outgoing SIP
* signaling.
*/
private boolean conferenceFocus = false;
/**
* Our video streaming policy.
*/
private boolean localVideoAllowed = false;
/**
* A reference to the <tt>SipMessageFactory</tt> instance that we should
* use when creating requests.
@ -48,11 +61,6 @@ public class CallSipImpl
*/
private final OperationSetBasicTelephonySipImpl parentOpSet;
/**
* Our video streaming policy.
*/
private boolean isLocalVideoAllowed = false;
/**
* Crates a CallSipImpl instance belonging to <tt>sourceProvider</tt> and
* initiated by <tt>CallCreator</tt>.
@ -405,8 +413,6 @@ public void processReplacingInvite(SipProvider jainSipProvider,
return;
}
//we just accepted the new peer and if we got here then it went well
//now let's hangup the other call.
try
@ -420,7 +426,6 @@ public void processReplacingInvite(SipProvider jainSipProvider,
callPeerToReplace.setState(
CallPeerState.FAILED, "Internal Error: " + ex);
}
}
/**
@ -473,7 +478,7 @@ public CallPeerSipImpl processInvite(SipProvider jainSipProvider,
public void setLocalVideoAllowed(boolean allowed)
throws OperationFailedException
{
this.isLocalVideoAllowed = allowed;
this.localVideoAllowed = allowed;
/*
* Record the setting locally and notify all peers.
@ -499,7 +504,7 @@ public void setLocalVideoAllowed(boolean allowed)
*/
public boolean isLocalVideoAllowed()
{
return isLocalVideoAllowed;
return localVideoAllowed;
}
/**
@ -563,4 +568,36 @@ public void removeVideoPropertyChangeListener(
peer.removeVideoPropertyChangeListener(listener);
}
}
/**
* Gets the indicator which determines whether the local peer represented by
* this <tt>Call</tt> is acting as a conference focus and thus should send
* the &quot;isfocus&quot; parameter in the Contact headers of its outgoing
* SIP signaling.
*
* @return <tt>true</tt> if the local peer represented by this <tt>Call</tt>
* is acting as a conference focus; otherwise, <tt>false</tt>
*/
boolean isConferenceFocus()
{
return conferenceFocus;
}
/**
* Sets the indicator which determines whether the local peer represented by
* this <tt>Call</tt> is acting as a conference focus and thus should send
* the &quot;isfocus&quot; parameter in the Contact headers of its outgoing
* SIP signaling
*
* @param conferenceFocus <tt>true</tt> if the local peer represented by
* this <tt>Call</tt> is to act as a conference focus; otherwise,
* <tt>false</tt>
*/
void setConferenceFocus(boolean conferenceFocus)
{
if (this.conferenceFocus != conferenceFocus)
{
this.conferenceFocus = conferenceFocus;
}
}
}

@ -0,0 +1,161 @@
/*
* 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.protocol.sip;
import net.java.sip.communicator.service.protocol.*;
/**
* Implements <tt>ConferenceMember</tt> for the SIP protocol.
*
* @author Lubomir Marinov
*/
public class ConferenceMemberSipImpl
extends AbstractConferenceMember
{
/**
* A Public Switched Telephone Network (PSTN) ALERTING or SIP 180 Ringing
* was returned for the outbound call; endpoint is being alerted.
*/
static final String ALERTING = "alerting";
/**
* The endpoint is a participant in the conference. Depending on the media
* policies, he/she can send and receive media to and from other
* participants.
*/
static final String CONNECTED = "connected";
/**
* Endpoint is dialing into the conference, not yet in the roster (probably
* being authenticated).
*/
static final String DIALING_IN = "dialing-in";
/**
* Focus has dialed out to connect the endpoint to the conference, but the
* endpoint is not yet in the roster (probably being authenticated).
*/
static final String DIALING_OUT = "dialing-out";
/**
* The endpoint is not a participant in the conference, and no active dialog
* exists between the endpoint and the focus.
*/
static final String DISCONNECTED = "disconnected";
/**
* Active signaling dialog exists between an endpoint and a focus, but
* endpoint is "on-hold" for this conference, i.e., he/she is neither
* "hearing" the conference mix nor is his/her media being mixed in the
* conference.
*/
static final String ON_HOLD = "on-hold";
/**
* Endpoint is not yet in the session, but it is anticipated that he/she
* will join in the near future.
*/
static final String PENDING = "pending";
/**
* The SIP address of this <tt>ConferenceMember</tt> as specified by the
* conference-info XML received from its <tt>conferenceFocusCallPeer</tt>.
*/
private final String address;
/**
* Initializes a new <tt>ConferenceMemberSipImpl</tt> instance with a
* specific SIP address as indicated by the conference-info XML received
* from its <tt>conferenceFocusCallPeer</tt>.
*
* @param conferenceFocusCallPeer the <tt>CallPeer</tt> which is the focus
* of the conference in which the new <tt>ConferenceMember</tt> participates
* @param address the SIP address of the new instance
*/
public ConferenceMemberSipImpl(
CallPeerSipImpl conferenceFocusCallPeer,
String address)
{
super(conferenceFocusCallPeer);
if (address == null)
throw new NullPointerException("address");
this.address = address;
}
/**
* Gets the SIP address of this <tt>ConferenceMember</tt> as specified by
* the conference-info XML received from its
* <tt>conferenceFocusCallPeer</tt>.
*
* @return the SIP address of this <tt>ConferenceMember</tt> as specified by
* the conference-info XML received from its
* <tt>conferenceFocusCallPeer</tt>
*/
public String getAddress()
{
return address;
}
/**
* Overrides {@link AbstractCallPeer#getDisplayName()} in order to return
* the SIP address of this <tt>ConferenceMember</tt> if the display name is
* empty.
*
* @return if the <tt>displayName</tt> property of this instance is an empty
* <tt>String</tt> value, returns the <tt>address</tt> property of this
* instance; otherwise, returns the value of the <tt>displayName</tt>
* property of this instance
*/
@Override
public String getDisplayName()
{
String displayName = super.getDisplayName();
if ((displayName == null) || (displayName.length() < 1))
{
String address = getAddress();
if ((address != null) && (address.length() > 0))
return address;
}
return displayName;
}
/**
* Sets the <tt>state</tt> property of this <tt>ConferenceMember</tt> by
* translating it from its conference-info XML endpoint status.
*
* @param endpointStatus the conference-info XML endpoint status of this
* <tt>ConferenceMember</tt> indicated by its
* <tt>conferenceFocusCallPeer</tt>
*/
void setEndpointStatus(String endpointStatus)
{
ConferenceMemberState state;
if (ALERTING.equalsIgnoreCase(endpointStatus))
state = ConferenceMemberState.ALERTING;
else if (CONNECTED.equalsIgnoreCase(endpointStatus))
state = ConferenceMemberState.CONNECTED;
else if (DIALING_IN.equalsIgnoreCase(endpointStatus))
state = ConferenceMemberState.DIALING_IN;
else if (DIALING_OUT.equalsIgnoreCase(endpointStatus))
state = ConferenceMemberState.DIALING_OUT;
else if (DISCONNECTED.equalsIgnoreCase(endpointStatus))
state = ConferenceMemberState.DISCONNECTED;
else if (ON_HOLD.equalsIgnoreCase(endpointStatus))
state = ConferenceMemberState.ON_HOLD;
else if (PENDING.equalsIgnoreCase(endpointStatus))
state = ConferenceMemberState.PENDING;
else
state = ConferenceMemberState.UNKNOWN;
setState(state);
}
}

@ -423,23 +423,50 @@ public void notify( Subscription subscription,
* @param reason the reason for the specified subscription state
*
* @throws OperationFailedException if anything goes wrong while sending out
* notifications.
* the notifications.
*/
public void notifyAll(String subscriptionState, String reason)
throws OperationFailedException
{
notifyAll(subscriptionState, reason, null);
}
/**
* Notifies all targets represented by the <tt>Subscription</tt>s managed by
* this instance which are accepted by a specific
* <tt>SubscriptionFilter</tt> about a specific subscription state and a
* specific reason for that subscription state via NOTIFY requests.
*
* @param subscriptionState the subscription state to be sent to all targets
* represented by the <tt>Subscription</tt>s managed by this instance which
* are accepted by <tt>filter</tt> via NOTIFY requests
* @param reason the reason for the specified subscription state
* @param filter the <tt>SubscriptionFilter</tt> to pick up the
* <tt>Subscription</tt>s managed by this instance to be notified about
* <tt>subscriptionState</tt>
* @throws OperationFailedException if anything goes wrong while sending out
* the notifications
*/
public void notifyAll(
String subscriptionState,
String reason,
SubscriptionFilter filter)
throws OperationFailedException
{
for (Subscription subscription : getSubscriptions())
notify(subscription, subscriptionState, reason);
if ((filter == null) || filter.accept(subscription))
notify(subscription, subscriptionState, reason);
}
/**
* Processes incoming subscribe requests.
*
* @param requestEvent the event containing the request we need to handle.
*
* @return <tt>true</tt> if we have handled and thus consumed the request
* and <tt>false</tt> otherwise.
* @param requestEvent the event containing the request we need to handle
* @return <tt>true</tt> if we have handled and thus consumed the request;
* <tt>false</tt>, otherwise
* @see MethodProcessor#processRequest(RequestEvent)
*/
@Override
public boolean processRequest(RequestEvent requestEvent)
{
Request request = requestEvent.getRequest();
@ -761,11 +788,12 @@ public boolean processRequest(RequestEvent requestEvent)
/**
* Handles an incoming response to a request we'vre previously sent.
*
* @param responseEvent the event we need to handle.
*
* @return <tt>true</tt> in case we've handles and thus consumed the event
* and <tt>false</tt> otherwise.
* @param responseEvent the event we need to handle
* @return <tt>true</tt> in case we've handles and thus consumed the event;
* <tt>false</tt>, otherwise
* @see MethodProcessor#processResponse(ResponseEvent)
*/
@Override
public boolean processResponse(ResponseEvent responseEvent)
{
Response response = responseEvent.getResponse();
@ -959,6 +987,29 @@ protected abstract byte[] createNotifyContent(
String reason);
}
/**
* Represents a filter for <tt>Subscription</tt>s i.e. it determines whether
* a specific <tt>Subscription</tt> is to be selected or deselected by the
* caller of the filter.
*/
public interface SubscriptionFilter
{
/**
* Determines whether the specified <tt>Subscription</tt> is accepted by
* this <tt>SubscriptionFilter</tt> i.e. whether the caller of this
* instance is to include or exclude the specified <tt>Subscription</tt>
* from their list of processed <tt>Subscription</tt>s.
*
* @param subscription the <tt>Subscription</tt> to be checked
* @return <tt>true</tt> if this <tt>SubscriptionFilter</tt> accepts
* the specified <tt>subscription</tt> i.e. the caller of this instance
* should include <tt>subscription</tt> in their list of processed
* <tt>Subscription</tt>s; otherwise, <tt>false</tt>
*/
public boolean accept(Subscription subscription);
}
/**
* Represents a <tt>TimerTask</tt> which times out a specific
* <tt>Subscription</tt> when its subscription duration expires.

@ -401,7 +401,7 @@ private Subscription getSubscription(String callId)
* subscription <tt>Address</tt>/Request URI and id tag of
* its Event header
* @throws OperationFailedException if we fail constructing or sending the
* subsctiption request.
* subscription request.
*/
public void poll(Subscription subscription)
throws OperationFailedException
@ -504,15 +504,21 @@ private void populateSubscribeRequest(
req.setHeader(expHeader);
}
/*
* Implements MethodProcessor#processRequest(RequestEvent). Handles only
* NOTIFY requests because they are the only requests concerning event
/**
* Implements {@link MethodProcessor#processRequest(RequestEvent)}. Handles
* only NOTIFY requests because they are the only requests concerning event
* package subscribers and if the processing of a given request requires
* event package-specific handling, delivers the request to the matching
* Subscription instance. Examples of such event package-specific handling
* include handling the termination of an existing Subscription and
* processing the bodies of the NOTIFY requests for active Subscriptions.
*
* @param requestEvent a <tt>RequestEvent</tt> specifying the SIP
* <tt>Request</tt> to be processed
* @return <tt>true</tt> if the SIP <tt>Request</tt> specified by
* <tt>requestEvent</tt> was processed; otherwise, <tt>false</tt>
*/
@Override
public boolean processRequest(RequestEvent requestEvent)
{
Request request = requestEvent.getRequest();
@ -704,16 +710,23 @@ public boolean processRequest(RequestEvent requestEvent)
return true;
}
/*
* Implements MethodProcessor#processResponse(ResponseEvent). Handles only
* responses to SUBSCRIBE requests because they are the only requests
* concerning event package subscribers (and the only requests sent by them,
* for that matter) and if the processing of a given response requires event
* package-specific handling, delivers the response to the matching
* Subscription instance. Examples of such event package-specific handling
* include letting the respective Subscription handle the success or failure
* in the establishment of a subscription.
/**
* Implements {@link MethodProcessor#processResponse(ResponseEvent)}.
* Handles only responses to SUBSCRIBE requests because they are the only
* requests concerning event package subscribers (and the only requests sent
* by them, for that matter) and if the processing of a given response
* requires event package-specific handling, delivers the response to the
* matching <tt>Subscription</tt> instance. Examples of such event
* package-specific handling include letting the respective
* <tt>Subscription</tt> handle the success or failure in the establishment
* of a subscription.
*
* @param responseEvent a <tt>ResponseEvent</tt> specifying the SIP
* <tt>Response</tt> to be processed
* @return <tt>true</tt> if the SIP <tt>Response</tt> specified by
* <tt>responseEvent</tt> was processed; otherwise, <tt>false</tt>
*/
@Override
public boolean processResponse(ResponseEvent responseEvent)
{
Response response = responseEvent.getResponse();
@ -995,17 +1008,25 @@ private void removeSubscription(String callId, Subscription subscription)
* the SUBSCRIBE request to be created and sent, to be added to
* the list of subscriptions managed by this instance
* @throws OperationFailedException if we fail constructing or sending the
* subsctiption request.
* subscription request.
*/
public void subscribe(Subscription subscription)
throws OperationFailedException
{
Dialog dialog = subscription.getDialog();
if ((dialog != null)
&& DialogState.TERMINATED.equals(dialog.getState()))
dialog = null;
//create the subscription
ClientTransaction subscribeTransaction = null;
try
{
subscribeTransaction
= createSubscription(subscription, subscriptionDuration);
= (dialog == null)
? createSubscription(subscription, subscriptionDuration)
: createSubscription(subscription, dialog, subscriptionDuration);
}
catch (OperationFailedException ex)
{
@ -1024,7 +1045,10 @@ public void subscribe(Subscription subscription)
// send the message
try
{
subscribeTransaction.sendRequest();
if (dialog == null)
subscribeTransaction.sendRequest();
else
dialog.sendRequest(subscribeTransaction);
}
catch (SipException ex)
{

@ -0,0 +1,54 @@
/*
* 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.protocol.sip;
import javax.sip.message.*;
/**
* Represents a listener which gets notified by the <tt>CallPeer</tt> it is
* registered with about the processing of SIP signaling that the
* <tt>CallPeer</tt> performs.
*
* @author Lubomir Marinov
*/
public interface MethodProcessorListener
{
/**
* Notifies this <tt>MethodProcessorListener</tt> that a specific
* <tt>CallPeer</tt> has processed a specific SIP <tt>Request</tt> and has
* replied to it with a specific SIP <tt>Response</tt>.
*
* @param sourceCallPeer the <tt>CallPeer</tt> which has processed the
* specified SIP <tt>Request</tt>
* @param request the SIP <tt>Request</tt> which has been processed by
* <tt>sourceCallPeer</tt>
* @param response the SIP <tt>Response</tt> sent by <tt>sourceCallPeer</tt>
* as a reply to the specified SIP <tt>request</tt>
*/
public void requestProcessed(
CallPeerSipImpl sourceCallPeer,
Request request,
Response response);
/**
* Notifies this <tt>MethodProcessorListener</tt> that a specific
* <tt>CallPeer</tt> has processed a specific SIP <tt>Response</tt> and has
* replied to it with a specific SIP <tt>Request</tt>.
*
* @param sourceCallPeer the <tt>CallPeer</tt> which has processed the
* specified SIP <tt>Response</tt>
* @param response the SIP <tt>Response</tt> which has been processed by
* <tt>sourceCallPeer</tt>
* @param request the SIP <tt>Request</tt> sent by <tt>sourceCallPeer</tt>
* as a reply to the specified SIP <tt>response</tt>
*/
public void responseProcessed(
CallPeerSipImpl sourceCallPeer,
Response response,
Request request);
}

@ -143,7 +143,26 @@ public Call createCall(Contact callee) throws OperationFailedException
}
/**
* Init and establish the specified call.
* Initializes a new outgoing <tt>Call</tt> with no peers in it. Intended
* for use by other <tt>OperationSet</tt>s willing to initialize
* <tt>Call</tt>s and willing to control their establishment in ways
* different than {@link #createOutgoingCall(Address, Message)}.
*
* @return a new outgoing <tt>Call</tt> with no peers in it
* @throws OperationFailedException if initializing the new outgoing
* <tt>Call</tt> fails
*/
synchronized CallSipImpl createOutgoingCall()
throws OperationFailedException
{
assertRegistered();
return new CallSipImpl(this);
}
/**
* Initializes and establishes a new outgoing <tt>Call</tt> to a callee with
* a specific <tt>Address</tt>.
*
* @param calleeAddress the address of the callee that we'd like to connect
* with.
@ -163,9 +182,7 @@ public Call createCall(Contact callee) throws OperationFailedException
private synchronized CallSipImpl createOutgoingCall(Address calleeAddress,
javax.sip.message.Message cause) throws OperationFailedException
{
assertRegistered();
CallSipImpl call = new CallSipImpl(this);
CallSipImpl call = createOutgoingCall();
call.invite(calleeAddress, cause);

@ -74,22 +74,20 @@ public void addVideoListener(CallPeer peer, VideoListener listener)
}
/**
* Implements OperationSetVideoTelephony#createLocalVisualComponent(
* CallPeer, VideoListener). Delegates to
* CallSession#createLocalVisualComponent(VideoListener) of the Call of the
* specified CallPeer because the CallSession manages the visual components
* which represent local video.
* Implements
* {@link OperationSetVideoTelephony#createLocalVisualComponent(CallPeer,
* VideoListener)}.
*
* @param peer the <tt>CallPeer</tt> that we are sending our local video to.
* @param listener the <tt>VideoListener</tt> where we'd like to retrieve
* the <tt>Component</tt> containing the local video.
*
* @return the <tt>Component</tt> containing the local video.
*
* @throws OperationFailedException if we fail extracting the local video.
*/
public Component createLocalVisualComponent(CallPeer peer,
VideoListener listener) throws OperationFailedException
public Component createLocalVisualComponent(
CallPeer peer,
VideoListener listener)
throws OperationFailedException
{
/**
* @todo update to neomedia.
@ -114,10 +112,9 @@ public Component createLocalVisualComponent(CallPeer peer,
}
/**
* Implements OperationSetVideoTelephony#disposeLocalVisualComponent(
* CallPeer, Component). Delegates to CallSession#disposeLocalVisualComponent(
* Component) of the Call of the specified CallPeer because the
* CallSession manages the visual components which represent local video.
* Implements
* {@link OperationSetVideoTelephony#disposeLocalVisualComponent(CallPeer,
* Component)}.
*
* @param peer the <tt>CallPeer</tt> whose local video component we'd like
* to dispose of.

@ -7,6 +7,7 @@ System-Bundle: yes
Import-Package: org.apache.log4j,
org.osgi.framework,
org.w3c.dom,
org.xml.sax,
net.java.sip.communicator.service.argdelegation,
net.java.sip.communicator.service.configuration,
net.java.sip.communicator.service.configuration.event,

@ -13,9 +13,9 @@
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.
* Provides a default implementation for most of the <tt>CallPeer</tt> methods
* with the purpose of only leaving custom protocol development to clients using
* the PhoneUI service.
*
* @author Emil Ivov
* @author Lubomir Marinov
@ -32,9 +32,8 @@ public abstract class AbstractCallPeer
= Logger.getLogger(AbstractCallPeer.class);
/**
* The constant which describes an empty set of
* <code>ConferenceMember</code>s (and which can be used to reduce
* allocations).
* The constant which describes an empty set of <tt>ConferenceMember</tt>s
* (and which can be used to reduce allocations).
*/
protected static final ConferenceMember[] NO_CONFERENCE_MEMBERS
= new ConferenceMember[0];
@ -46,8 +45,7 @@ public abstract class AbstractCallPeer
= new ArrayList<CallPeerListener>();
/**
* All the CallPeerSecurityListener-s registered with this
* CallPeer.
* All the CallPeerSecurityListener-s registered with this CallPeer.
*/
protected final List<CallPeerSecurityListener>
callPeerSecurityListeners
@ -71,23 +69,23 @@ public abstract class AbstractCallPeer
/**
* 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
* <tt>ConferenceMember</tt> 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.
* The list of <tt>ConferenceMember</tt>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.
* The list of <tt>CallPeerConferenceListener</tt>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
@ -111,7 +109,8 @@ public abstract class AbstractCallPeer
/**
* Registers the <tt>listener</tt> to the list of listeners that would be
* receiving CallPeerEvents
* receiving CallPeerEvents.
*
* @param listener a listener instance to register with this peer.
*/
public void addCallPeerListener(CallPeerListener listener)
@ -127,6 +126,7 @@ public void addCallPeerListener(CallPeerListener listener)
/**
* Unregisters the specified listener.
*
* @param listener the listener to unregister.
*/
public void removeCallPeerListener(CallPeerListener listener)
@ -141,7 +141,7 @@ public void removeCallPeerListener(CallPeerListener listener)
/**
* Registers the <tt>listener</tt> to the list of listeners that would be
* receiving CallPeerSecurityEvents
* receiving CallPeerSecurityEvents.
*
* @param listener a listener instance to register with this peer.
*/
@ -174,9 +174,9 @@ public void removeCallPeerSecurityListener(
}
/**
* 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>,
* 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.
@ -191,9 +191,9 @@ protected void fireCallPeerChangeEvent(String eventType,
/**
* 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>,
* 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.
@ -246,9 +246,9 @@ protected void fireCallPeerChangeEvent(String eventType,
}
/**
* 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>
* 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.
@ -283,9 +283,9 @@ protected void fireCallPeerSecurityOnEvent(int sessionType, String cipher,
}
/**
* 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>,
* 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
*/
@ -315,9 +315,9 @@ protected void fireCallPeerSecurityOffEvent(int sessionType)
}
/**
* 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>,
* 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
@ -357,8 +357,10 @@ protected void fireCallPeerSecurityMessageEvent(
* Returns a string representation of the peer in the form of
* <br/>
* Display Name &lt;address&gt;;status=CallPeerStatus
*
* @return a string representation of the peer and its state.
*/
@Override
public String toString()
{
return getDisplayName() + " <" + getAddress()
@ -367,12 +369,12 @@ public String toString()
/**
* 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.
* 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.
* web interface related to this peer or <tt>null</tt> if no such URL is
* available.
*/
public URL getCallInfoURL()
{
@ -392,9 +394,8 @@ public CallPeerState getState()
}
/**
* Causes this CallPeer to enter the specified state. The method also
* sets the currentStateStartDate field and fires a
* CallPeerChangeEvent.
* 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
@ -423,9 +424,8 @@ public void setState(CallPeerState newState, String reason)
}
/**
* Causes this CallPeer to enter the specified state. The method also
* sets the currentStateStartDate field and fires a
* CallPeerChangeEvent.
* 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.
*/
@ -435,15 +435,14 @@ public void setState(CallPeerState newState)
}
/**
* 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>.
* Gets the time at which this <tt>CallPeer</tt> transitioned into a state
* (likely {@link CallPeerState#CONNECTED}) marking the start of the
* duration of the participation in a <tt>Call</tt>.
*
* @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
* @return the time at which this <tt>CallPeer</tt> transitioned into a
* state marking the start of the duration of the participation in a
* <tt>Call</tt> or {@link CallPeer#CALL_DURATION_START_TIME_UNKNOWN} if
* such a transition has not been performed
*/
public long getCallDurationStartTime()
{
@ -451,14 +450,14 @@ public long getCallDurationStartTime()
}
/**
* Determines whether the audio stream (if any) being sent to this
* peer is mute.
* 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
* @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()
{
@ -508,6 +507,7 @@ public void setConferenceFocus(boolean conferenceFocus)
* 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()
@ -533,6 +533,7 @@ public ConferenceMember[] getConferenceMembers()
* 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()
@ -541,19 +542,17 @@ public int getConferenceMemberCount()
}
/**
* Adds a specific <code>ConferenceMember</code> to the list of
* <code>ConferenceMember</code>s reported by this peer through
* Adds a specific <tt>ConferenceMember</tt> to the list of
* <tt>ConferenceMember</tt>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.
* <tt>CallPeerConferenceEvent#CONFERENCE_MEMBER_ADDED</tt> to
* the currently registered <tt>CallPeerConferenceListener</tt>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.
* @param conferenceMember a <tt>ConferenceMember</tt> to be added to the
* list of <tt>ConferenceMember</tt> reported by this peer. If the specified
* <tt>ConferenceMember</tt> is already contained in the list, it is not
* added again and no event is fired.
*/
public void addConferenceMember(ConferenceMember conferenceMember)
{
@ -573,18 +572,17 @@ public void addConferenceMember(ConferenceMember conferenceMember)
}
/**
* Removes a specific <code>ConferenceMember</code> from the list of
* <code>ConferenceMember</code>s reported by this peer through
* Removes a specific <tt>ConferenceMember</tt> from the list of
* <tt>ConferenceMember</tt>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.
* <tt>CallPeerConferenceEvent#CONFERENCE_MEMBER_REMOVED</tt> to
* the currently registered <tt>CallPeerConferenceListener</tt>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.
* @param conferenceMember a <tt>ConferenceMember</tt> to be removed from
* the list of <tt>ConferenceMember</tt> reported by this peer. If the
* specified <tt>ConferenceMember</tt> is no contained in the list, no event
* is fired.
*/
public void removeConferenceMember(ConferenceMember conferenceMember)
{
@ -603,10 +601,12 @@ public void removeConferenceMember(ConferenceMember 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.
* Implements
* <tt>CallPeer#addCallPeerConferenceListener(
* CallPeerConferenceListener)</tt>. In the fashion of the addition of the
* other listeners, does not throw an exception on attempting to add a
* <tt>null</tt> listeners and just ignores the call.
*
* @param listener the <tt>CallPeerConferenceListener</tt> to add
*/
public void addCallPeerConferenceListener(
@ -621,8 +621,10 @@ public void addCallPeerConferenceListener(
}
/**
* Implements CallPeer#removeCallPeerConferenceListener(
* CallPeerConferenceListener).
* Implements
* <tt>CallPeer#removeCallPeerConferenceListener(
* CallPeerConferenceListener)</tt>.
*
* @param listener the <tt>CallPeerConferenceListener</tt> to remove
*/
public void removeCallPeerConferenceListener(
@ -704,13 +706,12 @@ public void removeConferenceMembersSoundLevelListener(
}
/**
* Fires a specific <code>CallPeerConferenceEvent</code> to the
* <code>CallPeerConferenceListener</code>s interested in changes in
* the conference-related information provided by this peer.
* Fires a specific <tt>CallPeerConferenceEvent</tt> to the
* <tt>CallPeerConferenceListener</tt>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
* @param conferenceEvent a <tt>CallPeerConferenceEvent</tt> to be fired and
* carrying the event data
*/
protected void fireCallPeerConferenceEvent(
CallPeerConferenceEvent conferenceEvent)
@ -728,6 +729,34 @@ protected void fireCallPeerConferenceEvent(
int eventID = conferenceEvent.getEventID();
if (logger.isDebugEnabled())
{
String eventIDString;
switch (eventID)
{
case CallPeerConferenceEvent.CONFERENCE_FOCUS_CHANGED:
eventIDString = "CONFERENCE_FOCUS_CHANGED";
break;
case CallPeerConferenceEvent.CONFERENCE_MEMBER_ADDED:
eventIDString = "CONFERENCE_MEMBER_ADDED";
break;
case CallPeerConferenceEvent.CONFERENCE_MEMBER_REMOVED:
eventIDString = "CONFERENCE_MEMBER_REMOVED";
break;
default:
eventIDString = "UNKNOWN";
break;
}
logger
.debug(
"Firing CallPeerConferenceEvent with ID "
+ eventIDString
+ " to "
+ listeners.length
+ " listeners");
}
for (CallPeerConferenceListener listener : listeners)
switch (eventID)
{

@ -10,40 +10,42 @@
* Provides operations necessary to create and handle conferencing calls.
*
* @author Emil Ivov
* @author Lubomir Marinov
*/
public interface OperationSetTelephonyConferencing
extends OperationSet
{
/**
* Creates a conference call with the specified callees as call
* peers.
* Creates a conference call with the specified callees as call peers.
*
* @param callees
* the list of addresses that we should call
* @param callees the list of addresses that we should call
* @return the newly created conference call containing all CallPeers
* @throws OperationNotSupportedException
* if the provider does not have any conferencing features.
* @throws OperationFailedException if establishing the conference call
* fails
* @throws OperationNotSupportedException if the provider does not have any
* conferencing features.
*/
public Call createConfCall(String[] callees)
throws OperationNotSupportedException;
throws OperationFailedException,
OperationNotSupportedException;
/**
* Invites the callee represented by the specified uri to an already
* existing call. The difference between this method and createConfCall is
* that inviteCalleeToCall allows a user to transform an existing 1 to 1
* call into a conference call, or add new peers to an already
* established conference.
* call into a conference call, or add new peers to an already established
* conference.
*
* @param uri
* the callee to invite to an existing conf call.
* @param existingCall
* the call that we should invite the callee to.
* @return the CallPeer object corresponding to the callee
* represented by the specified uri.
* @throws OperationNotSupportedException
* if allowing additional callees to a pre-established call is
* not supported.
* @param uri the callee to invite to an existing conf call.
* @param call the call that we should invite the callee to.
* @return the CallPeer object corresponding to the callee represented by
* the specified uri.
* @throws OperationFailedException if inviting the specified callee to the
* specified call fails
* @throws OperationNotSupportedException if allowing additional callees to
* a pre-established call is not supported.
*/
public CallPeer inviteCalleeToCall(String uri, Call existingCall)
throws OperationNotSupportedException;
public CallPeer inviteCalleeToCall(String uri, Call call)
throws OperationFailedException,
OperationNotSupportedException;
}

Loading…
Cancel
Save