diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java
index 34ebaa574..2c8922489 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java
@@ -27,6 +27,7 @@
*
* @author Lyubomir Marinov
* @author Sebastien Vincent
+ * @author Boris Grozev
*/
public class OperationSetTelephonyConferencingJabberImpl
extends AbstractOperationSetTelephonyConferencing<
@@ -506,4 +507,42 @@ private void handleCoin(CallPeerJabberImpl callPeer, CoinIQ coinIQ)
{
setConferenceInfoXML(callPeer, -1, coinIQ.getChildElementXML());
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * For COINs (XEP-0298), we use the attributes of the
+ * conference-info element to piggyback a Jingle SID. This is
+ * temporary and should be removed once we choose a better way to pass the
+ * SID.
+ */
+ protected ConferenceInfoDocument getCurrentConferenceInfo(CallPeer callPeer)
+ {
+ ConferenceInfoDocument confInfo
+ = super.getCurrentConferenceInfo(callPeer);
+
+ if (callPeer instanceof CallPeerJabberImpl)
+ {
+ confInfo.setSid(((CallPeerJabberImpl)callPeer).getSID());
+ }
+ return confInfo;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String getLocalEntity(CallPeer callPeer)
+ {
+ return "xmpp:" + parentProvider.getOurJID();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String getLocalDisplayName()
+ {
+ return null;
+ }
}
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetTelephonyConferencingSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetTelephonyConferencingSipImpl.java
index 596b92b75..fa58e59c2 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetTelephonyConferencingSipImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetTelephonyConferencingSipImpl.java
@@ -30,6 +30,7 @@
* Implements OperationSetTelephonyConferencing for SIP.
*
* @author Lyubomir Marinov
+ * @author Boris Grozev
*/
public class OperationSetTelephonyConferencingSipImpl
extends AbstractOperationSetTelephonyConferencing<
@@ -552,7 +553,7 @@ private void getUserXML(CallPeer callPeer, StringBuffer xml)
* Implements the protocol-dependent part of the logic of inviting a callee
* to a Call. The protocol-independent part of that logic is
* implemented by
- * {@link AbstractOperationSetTelephonyConferencing#inviteCalleToCall(String,Call)}.
+ * {@link AbstractOperationSetTelephonyConferencing#inviteCalleeToCall(String,Call)}.
*/
@Override
protected CallPeerSipImpl doInviteCalleeToCall(
@@ -1108,4 +1109,35 @@ protected void processTerminatedRequest(
}
}
}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String getLocalEntity(CallPeer callPeer)
+ {
+ if (callPeer instanceof CallPeerSipImpl)
+ {
+ Dialog dialog = ((CallPeerSipImpl)callPeer).getDialog();
+
+ if (dialog != null)
+ {
+ Address localPartyAddress = dialog.getLocalParty();
+
+ if (localPartyAddress != null)
+ return stripParametersFromAddress(
+ localPartyAddress.getURI().toString());
+ }
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String getLocalDisplayName()
+ {
+ return parentProvider.getOurDisplayName();
+ }
}
diff --git a/src/net/java/sip/communicator/service/protocol/AbstractCallPeer.java b/src/net/java/sip/communicator/service/protocol/AbstractCallPeer.java
index 7a44d2009..a1fbf9976 100644
--- a/src/net/java/sip/communicator/service/protocol/AbstractCallPeer.java
+++ b/src/net/java/sip/communicator/service/protocol/AbstractCallPeer.java
@@ -131,6 +131,19 @@ public abstract class AbstractCallPeer unmodifiableConferenceMembers;
+ /**
+ * The last Conference Information (RFC4575) document sent to this
+ * CallPeer
+ */
+ private ConferenceInfoDocument lastConferenceInfoSent = null;
+
+ /**
+ * The time (as obtained by System.currentTimeMillis() at which
+ * a Conference Information (RFC4575) document was last sent to this
+ * CallPeer.
+ */
+ private long lastConferenceInfoSentTimestamp = -1;
+
/**
* Initializes a new AbstractCallPeer instance.
*/
diff --git a/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetTelephonyConferencing.java b/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetTelephonyConferencing.java
index 37be06b43..048f17bf8 100644
--- a/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetTelephonyConferencing.java
+++ b/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetTelephonyConferencing.java
@@ -33,6 +33,7 @@
* @param
*
* @author Lyubomir Marinov
+ * @author Boris Grozev
*/
public abstract class AbstractOperationSetTelephonyConferencing<
ProtocolProviderServiceT extends ProtocolProviderService,
@@ -993,4 +994,175 @@ protected static String stripParametersFromAddress(String address)
}
return address;
}
+
+ /**
+ * Creates a ConferenceInfoDocument which describes the current
+ * state of the conference in which callPeer participates.
+ *
+ * @return a ConferenceInfoDocument which describes the current
+ * state of the conference in which this CallPeer participates.
+ */
+ protected ConferenceInfoDocument getCurrentConferenceInfo(CallPeer callPeer)
+ {
+ ConferenceInfoDocument confInfo;
+ try
+ {
+ confInfo = new ConferenceInfoDocument();
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ confInfo.setState(ConferenceInfoDocument.State.FULL);
+ confInfo.setEntity(getLocalEntity(callPeer));
+
+ Call call = callPeer.getCall();
+ List conferenceCallPeers = CallConference.getCallPeers(call);
+ confInfo.setUserCount(
+ 1 /* the local peer/user */ + conferenceCallPeers.size());
+
+ /* The local user */
+ addPeerToConferenceInfo(confInfo, callPeer, false);
+
+ /* Remote users */
+ for (CallPeer conferenceCallPeer : conferenceCallPeers)
+ addPeerToConferenceInfo(confInfo, conferenceCallPeer, true);
+
+ return null;
+ }
+
+ /**
+ * Adds a user element to confInfo which describes
+ * callPeer, or the local peer if remote is false.
+ *
+ * @param confInfo the ConferenceInformationDocument to which to
+ * add a user element
+ * @param callPeer the CallPeer which should be described
+ * @param remote true to describe callPeer, or
+ * false to describe the local peer.
+ */
+ private void addPeerToConferenceInfo(
+ ConferenceInfoDocument confInfo,
+ CallPeer callPeer,
+ boolean remote)
+ {
+ String entity
+ = remote
+ ? callPeer.getURI()
+ : getLocalEntity(callPeer);
+ ConferenceInfoDocument.User user = confInfo.addNewUser(entity);
+
+ String displayName
+ = remote
+ ? callPeer.getDisplayName()
+ : getLocalDisplayName();
+ user.setDisplayText(displayName);
+
+ ConferenceInfoDocument.Endpoint endpoint
+ = user.addNewEndpoint(entity);
+
+ endpoint.setStatus(
+ remote
+ ? getEndpointStatus(callPeer)
+ : ConferenceInfoDocument.EndpointStatusType.connected);
+
+ if (callPeer instanceof MediaAwareCallPeer,?,?>)
+ {
+ MediaAwareCallPeer,?,?> mediaAwarePeer
+ = (MediaAwareCallPeer,?,?>) callPeer;
+ CallPeerMediaHandler> mediaHandler
+ = mediaAwarePeer.getMediaHandler();
+ int id = 1;
+
+ for (MediaType mediaType : MediaType.values())
+ {
+ MediaStream stream = mediaHandler.getStream(mediaType);
+ if (stream != null)
+ {
+ ConferenceInfoDocument.Media media
+ = endpoint.addNewMedia(Integer.toString(id));
+ long srcId
+ = remote
+ ? getRemoteSourceID(mediaAwarePeer, mediaType)
+ : stream.getLocalSourceID();
+
+ if (srcId != -1)
+ media.setSrcId(Long.toString(srcId));
+
+ media.setType(mediaType.toString());
+
+ MediaDirection direction
+ = remote
+ ? getRemoteDirection(mediaAwarePeer, mediaType)
+ : stream.getDirection();
+
+ if (direction == null)
+ direction = MediaDirection.INACTIVE;
+
+ media.setStatus(direction.toString());
+ id++;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns a string to be used for the entity attribute of the
+ * user element for the local peer, in a Conference Information
+ * document to be sent to callPeer
+ *
+ * @param callPeer The CallPeer for which we are creating a
+ * Conference Information document.
+ * @return a string to be used for the entity attribute of the
+ * user element for the local peer, in a Conference Information
+ * document to be sent to callPeer
+ */
+ protected abstract String getLocalEntity(CallPeer callPeer);
+
+ /**
+ * Returns the display name for the local peer, which is to be used when
+ * we send Conference Information.
+ * @return the display name for the local peer, which is to be used when
+ * we send Conference Information.
+ */
+ protected abstract String getLocalDisplayName();
+
+ /**
+ * Gets the EndpointStatusType to use when describing
+ * callPeer in a Conference Information document.
+ *
+ * @param callPeer the CallPeer which is to get its state described
+ * in a status XML element of an endpoint XML element
+ * @return the EndpointStatusType to use when describing
+ * callPeer in a Conference Information document.
+ */
+ private ConferenceInfoDocument.EndpointStatusType getEndpointStatus(
+ CallPeer callPeer)
+ {
+ CallPeerState callPeerState = callPeer.getState();
+
+ if (CallPeerState.ALERTING_REMOTE_SIDE.equals(callPeerState))
+ return ConferenceInfoDocument.EndpointStatusType.alerting;
+ if (CallPeerState.CONNECTING.equals(callPeerState)
+ || CallPeerState
+ .CONNECTING_WITH_EARLY_MEDIA.equals(callPeerState))
+ return ConferenceInfoDocument.EndpointStatusType.pending;
+ if (CallPeerState.DISCONNECTED.equals(callPeerState))
+ return ConferenceInfoDocument.EndpointStatusType.disconnected;
+ if (CallPeerState.INCOMING_CALL.equals(callPeerState))
+ return ConferenceInfoDocument.EndpointStatusType.dialing_in;
+ if (CallPeerState.INITIATING_CALL.equals(callPeerState))
+ return ConferenceInfoDocument.EndpointStatusType.dialing_out;
+
+ /*
+ * he/she is neither "hearing" the conference mix nor is his/her
+ * media being mixed in the conference
+ */
+ if (CallPeerState.ON_HOLD_LOCALLY.equals(callPeerState)
+ || CallPeerState.ON_HOLD_MUTUALLY.equals(callPeerState))
+ return ConferenceInfoDocument.EndpointStatusType.on_hold;
+ if (CallPeerState.CONNECTED.equals(callPeerState))
+ return ConferenceInfoDocument.EndpointStatusType.connected;
+ return null;
+ }
}