aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java')
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java629
1 files changed, 461 insertions, 168 deletions
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java
index 547ebe8..48207c2 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java
@@ -37,9 +37,9 @@ import java.util.*;
* Add one or multiple requests of the same type by calling
* {@link #addAllocateChannelsReq(boolean, String, boolean, java.util.List)}}
* or {@link #addExpireChannelsReq(ColibriConferenceIQ)}
- * or {@link #addTransportUpdateReq(boolean, java.util.Map, ColibriConferenceIQ)}
- * or {@link #addBundleTransportUpdateReq(
- * boolean, IceUdpTransportPacketExtension, ColibriConferenceIQ)}.
+ * or {@link #addRtpDescription(Map, ColibriConferenceIQ)}
+ * and {@link #addSSSRCGroupsInfo(Map, ColibriConferenceIQ)}
+ * and {@link #addSSSRCInfo(Map, ColibriConferenceIQ)}.
* </li>
* <li>
* Compile the request by calling {@link #getRequest(String)}. Then send it to
@@ -119,6 +119,20 @@ public class ColibriBuilder
private SimulcastMode simulcastMode;
/**
+ * Specifies the audio packet delay that will be set on all created audio
+ * channels. When set to <tt>null</tt> the builder will clear the attribute
+ * which stands for 'undefined'.
+ **/
+ private Integer audioPacketDelay;
+
+ /**
+ * Channel 'rtp-level-relay-type' option that will be used with all created
+ * audio channel. Possible values: mixer or translator (default).
+ *
+ */
+ private RTPLevelRelayType rtpLevelRelayType;
+
+ /**
* Creates new instance of {@link ColibriBuilder} for given
* <tt>conferenceState</tt>.
*
@@ -161,18 +175,26 @@ public class ColibriBuilder
* @param contents the list of {@link ContentPacketExtension} describing
* channels media.
*
- * @return this instance fo calls chaining purpose.
+ * @return <tt>true</tt> if the request yields any changes in Colibri
+ * channels state on the bridge or <tt>false</tt> otherwise.
+ * In general when <tt>false</tt> is returned for all
+ * combined requests it makes no sense to send it.
*/
- public ColibriBuilder addAllocateChannelsReq(
- boolean useBundle,
- String endpointName,
- boolean peerIsInitiator,
+ public boolean addAllocateChannelsReq(
+ boolean useBundle,
+ String endpointName,
+ boolean peerIsInitiator,
List<ContentPacketExtension> contents)
{
+ Objects.requireNonNull(endpointName, "endpointName");
+ Objects.requireNonNull(contents, "contents");
+
assertRequestType(RequestType.ALLOCATE_CHANNELS);
request.setType(IQ.Type.GET);
+ boolean hasAnyChanges = false;
+
for (ContentPacketExtension cpe : contents)
{
MediaType mediaType = JingleUtils.getMediaType(cpe);
@@ -193,7 +215,7 @@ public class ColibriBuilder
remoteChannelRequest.setChannelBundleId(endpointName);
}
- if (mediaType != MediaType.DATA)
+ if (remoteChannelRequest instanceof ColibriConferenceIQ.Channel)
{
RtpDescriptionPacketExtension rdpe
= cpe.getFirstChildOfType(
@@ -213,6 +235,13 @@ public class ColibriBuilder
remoteRtpChannelRequest.setAdaptiveLastN(adaptiveLastN);
remoteRtpChannelRequest.setAdaptiveSimulcast(adaptiveSimulcast);
remoteRtpChannelRequest.setSimulcastMode(simulcastMode);
+ if (MediaType.AUDIO.equals(mediaType))
+ {
+ // When audioPacketDelay is null it will clear the attribute
+ remoteRtpChannelRequest.setPacketDelay(audioPacketDelay);
+ // Set rtp packet relay type for this channel
+ remoteRtpChannelRequest.setRTPLevelRelayType(rtpLevelRelayType);
+ }
}
// Copy transport
@@ -221,13 +250,17 @@ public class ColibriBuilder
copyTransportOnChannel(cpe, remoteChannelRequest);
}
- if (mediaType != MediaType.DATA)
+ if (remoteChannelRequest instanceof ColibriConferenceIQ.Channel)
{
+ hasAnyChanges = true;
+
contentRequest.addChannel(
(ColibriConferenceIQ.Channel) remoteChannelRequest);
}
else
{
+ hasAnyChanges = true;
+
contentRequest.addSctpConnection(
(ColibriConferenceIQ.SctpConnection) remoteChannelRequest);
}
@@ -246,6 +279,8 @@ public class ColibriBuilder
IceUdpTransportPacketExtension.class);
if (transport != null)
{
+ hasAnyChanges = true;
+
bundle.setTransport(
IceUdpTransportPacketExtension
.cloneTransportAndCandidates(transport, true));
@@ -254,106 +289,38 @@ public class ColibriBuilder
request.addChannelBundle(bundle);
}
- return this;
- }
-
- /**
- * Adds next ICE transport update request to
- * {@link RequestType#TRANSPORT_UPDATE} query currently being built.
- *
- * @param initiator the value that will be set in 'initiator'
- * attribute({@link ColibriConferenceIQ.Channel#initiator}).
- * @param map the map of content name to transport extensions. Maps
- * transport to media types.
- * @param localChannelsInfo {@link ColibriConferenceIQ} holding info about
- * Colibri channels to be updated.
- *
- * @return this instance fo calls chaining purpose.
- */
- public ColibriBuilder addTransportUpdateReq(
- boolean initiator,
- Map<String, IceUdpTransportPacketExtension> map,
- ColibriConferenceIQ localChannelsInfo)
- {
- if (conferenceState == null
- || StringUtils.isNullOrEmpty(conferenceState.getID()))
- {
- // We are not initialized yet
- return null;
- }
-
- assertRequestType(RequestType.TRANSPORT_UPDATE);
-
- request.setType(IQ.Type.SET);
-
- for (Map.Entry<String,IceUdpTransportPacketExtension> e
- : map.entrySet())
- {
- String contentName = e.getKey();
- ColibriConferenceIQ.ChannelCommon channel
- = getColibriChannel(localChannelsInfo, contentName);
-
- if (channel != null)
- {
- IceUdpTransportPacketExtension transport
- = IceUdpTransportPacketExtension
- .cloneTransportAndCandidates(e.getValue(), true);
-
- ColibriConferenceIQ.ChannelCommon channelRequest
- = channel instanceof ColibriConferenceIQ.Channel
- ? new ColibriConferenceIQ.Channel()
- : new ColibriConferenceIQ.SctpConnection();
-
- channelRequest.setID(channel.getID());
- channelRequest.setEndpoint(channel.getEndpoint());
- channelRequest.setInitiator(initiator);
- channelRequest.setTransport(transport);
-
- if (channelRequest instanceof ColibriConferenceIQ.Channel)
- {
- request.getOrCreateContent(contentName)
- .addChannel(
- (ColibriConferenceIQ.Channel) channelRequest);
- }
- else
- {
- request.getOrCreateContent(contentName)
- .addSctpConnection(
- (ColibriConferenceIQ.SctpConnection) channelRequest);
- }
- }
- }
- return this;
+ return hasAnyChanges;
}
/**
- * Adds next request to {@link RequestType#BUNDLE_TRANSPORT_UPDATE} query.
- * @param initiator the value that will be set in 'initiator'
- * attribute({@link ColibriConferenceIQ.Channel#initiator}).
+ * Adds next request to {@link RequestType#CHANNEL_INFO_UPDATE} query.
* @param localChannelsInfo the {@link ColibriConferenceIQ} instance that
* describes the channel for which bundle transport will be updated.
* It should contain the description of only one "channel bundle".
* If it contains more than one then the first one will be used.
- * @return this instance for calls chaining purpose.
+ * @return <tt>true</tt> if the request yields any changes in Colibri
+ * channels state on the bridge or <tt>false</tt> otherwise.
+ * In general when <tt>false</tt> is returned for all
+ * combined requests it makes no sense to send it.
* @throws IllegalArgumentException if <tt>localChannelsInfo</tt> does not
* describe any channel bundles.
*/
- public ColibriBuilder addBundleTransportUpdateReq(
- boolean initiator,
- IceUdpTransportPacketExtension transport,
- ColibriConferenceIQ localChannelsInfo)
+ public boolean addBundleTransportUpdateReq(
+ IceUdpTransportPacketExtension transport,
+ ColibriConferenceIQ localChannelsInfo)
throws IllegalArgumentException
{
- // FIXME:'initiator' not used on bundle transport update ?
+ Objects.requireNonNull(transport, "transport");
+ Objects.requireNonNull(localChannelsInfo, "localChannelsInfo");
if (conferenceState == null
|| StringUtils.isNullOrEmpty(conferenceState.getID()))
{
// We are not initialized yet
- return null;
+ return false;
}
- assertRequestType(RequestType.BUNDLE_TRANSPORT_UPDATE);
+ assertRequestType(RequestType.CHANNEL_INFO_UPDATE);
request.setType(IQ.Type.SET);
@@ -371,7 +338,7 @@ public class ColibriBuilder
else
{
throw new IllegalArgumentException(
- "Expected ChannelBundle as not found");
+ "Expected ChannelBundle as not found");
}
ColibriConferenceIQ.ChannelBundle bundleUpdate
@@ -387,7 +354,7 @@ public class ColibriBuilder
request.addChannelBundle(bundleUpdate);
- return this;
+ return true;
}
/**
@@ -395,15 +362,20 @@ public class ColibriBuilder
* {@link RequestType#EXPIRE_CHANNELS} query currently being built.
* @param channelInfo the {@link ColibriConferenceIQ} instance that contains
* info about the channels to be expired.
- * @return this instance for the purpose of calls chaining.
+ * @return <tt>true</tt> if the request yields any changes in Colibri
+ * channels state on the bridge or <tt>false</tt> otherwise.
+ * In general when <tt>false</tt> is returned for all
+ * combined requests it makes no sense to send it.
*/
- public ColibriBuilder addExpireChannelsReq(ColibriConferenceIQ channelInfo)
+ public boolean addExpireChannelsReq(ColibriConferenceIQ channelInfo)
{
+ Objects.requireNonNull(channelInfo, "channelInfo");
+
// Formulate the ColibriConferenceIQ request which is to be sent.
if (conferenceState == null
|| StringUtils.isNullOrEmpty(conferenceState.getID()))
{
- return null;
+ return false;
}
assertRequestType(RequestType.EXPIRE_CHANNELS);
@@ -411,7 +383,7 @@ public class ColibriBuilder
request.setType(IQ.Type.SET);
for (ColibriConferenceIQ.Content expiredContent
- : channelInfo.getContents())
+ : channelInfo.getContents())
{
ColibriConferenceIQ.Content stateContent
= conferenceState.getContent(expiredContent.getName());
@@ -420,7 +392,7 @@ public class ColibriBuilder
{
ColibriConferenceIQ.Content requestContent
= request.getOrCreateContent(
- stateContent.getName());
+ stateContent.getName());
for (ColibriConferenceIQ.Channel expiredChannel
: expiredContent.getChannels())
@@ -490,7 +462,7 @@ public class ColibriBuilder
*/
/*if (stateContent.getChannelCount() == 1)
{
- stateChannel = stateContent.getChannel(0);
+ stateChannel = stateContent.getRtpChannel(0);
ColibriConferenceIQ.Channel channelRequest
= new ColibriConferenceIQ.Channel();
@@ -537,7 +509,294 @@ public class ColibriBuilder
}
}
- return this;
+ return hasAnyChannelsToExpire;
+ }
+
+ /**
+ * Adds next payload type information update request to
+ * {@link RequestType#CHANNEL_INFO_UPDATE} query currently being built.
+ *
+ * @param map the map of content name to RTP description packet extension.
+ * @param localChannelsInfo {@link ColibriConferenceIQ} holding info about
+ * Colibri channels to be updated.
+ *
+ * @return <tt>true</tt> if the request yields any changes in Colibri
+ * channels state on the bridge or <tt>false</tt> otherwise.
+ * In general when <tt>false</tt> is returned for all
+ * combined requests it makes no sense to send it.
+ */
+ public boolean addRtpDescription(
+ Map<String, RtpDescriptionPacketExtension> map,
+ ColibriConferenceIQ localChannelsInfo)
+ {
+ Objects.requireNonNull(map, "map");
+ Objects.requireNonNull(localChannelsInfo, "localChannelsInfo");
+
+ if (conferenceState == null
+ || StringUtils.isNullOrEmpty(conferenceState.getID()))
+ {
+ // We are not initialized yet
+ return false;
+ }
+
+ assertRequestType(RequestType.CHANNEL_INFO_UPDATE);
+
+ request.setType(IQ.Type.SET);
+
+ boolean anyUpdates = false;
+
+ for (Map.Entry<String, RtpDescriptionPacketExtension> e
+ : map.entrySet())
+ {
+ String contentName = e.getKey();
+ ColibriConferenceIQ.ChannelCommon channel
+ = getColibriChannel(localChannelsInfo, contentName);
+
+ if (channel != null
+ && channel instanceof ColibriConferenceIQ.Channel)
+ {
+ RtpDescriptionPacketExtension rtpPE = e.getValue();
+ if (rtpPE == null)
+ {
+ continue;
+ }
+
+ List<PayloadTypePacketExtension> pts = rtpPE.getPayloadTypes();
+ if (pts == null || pts.isEmpty())
+ {
+ continue;
+ }
+
+ anyUpdates = true;
+
+ ColibriConferenceIQ.Channel channelRequest
+ = (ColibriConferenceIQ.Channel) getRequestChannel(
+ request.getOrCreateContent(contentName),
+ channel);
+ if (channelRequest == null)
+ {
+ channelRequest = new ColibriConferenceIQ.Channel();
+ channelRequest.setID(channel.getID());
+ }
+
+ for (PayloadTypePacketExtension ptPE : pts)
+ {
+ channelRequest.addPayloadType(ptPE);
+ }
+ }
+ }
+
+ return anyUpdates;
+ }
+
+ /**
+ * Adds next SSRC information update request to
+ * {@link RequestType#CHANNEL_INFO_UPDATE} query currently being built.
+ *
+ * @param ssrcMap the map of content name to the list of
+ * <tt>SourcePacketExtension</tt>.
+ * @param localChannelsInfo {@link ColibriConferenceIQ} holding info about
+ * Colibri channels to be updated.
+ *
+ * @return <tt>true</tt> if the request yields any changes in Colibri
+ * channels state on the bridge or <tt>false</tt> otherwise.
+ * In general when <tt>false</tt> is returned for all
+ * combined requests it makes no sense to send it.
+ */
+ public boolean addSSSRCInfo(
+ Map<String, List<SourcePacketExtension>> ssrcMap,
+ ColibriConferenceIQ localChannelsInfo)
+ {
+ Objects.requireNonNull(ssrcMap, "ssrcMap");
+ Objects.requireNonNull(localChannelsInfo, "localChannelsInfo");
+
+ if (conferenceState == null
+ || StringUtils.isNullOrEmpty(conferenceState.getID()))
+ {
+ // We are not initialized yet
+ return false;
+ }
+
+ assertRequestType(RequestType.CHANNEL_INFO_UPDATE);
+
+ request.setType(IQ.Type.SET);
+
+ boolean anyUpdates = false;
+
+ // Go over SSRCs
+ for (String contentName : ssrcMap.keySet())
+ {
+ // Get channel from local channel info
+ ColibriConferenceIQ.ChannelCommon rtpChanel
+ = getRtpChannel(localChannelsInfo, contentName);
+ if (rtpChanel == null)
+ {
+ // There's no channel for this content name in localChannelsInfo
+ continue;
+ }
+
+ anyUpdates = true;
+
+ // Ok we have channel for this content, let's add SSRCs
+ ColibriConferenceIQ.Channel reqChannel
+ = (ColibriConferenceIQ.Channel) getRequestChannel(
+ request.getOrCreateContent(contentName), rtpChanel);
+
+ for (SourcePacketExtension ssrc : ssrcMap.get(contentName))
+ {
+ reqChannel.addSource(ssrc.copy());
+ }
+
+ if (reqChannel.getSources() == null
+ || reqChannel.getSources().isEmpty())
+ {
+ // Put an empty source to remove all sources
+ SourcePacketExtension emptySource = new SourcePacketExtension();
+ emptySource.setSSRC(-1L);
+ reqChannel.addSource(emptySource);
+ }
+ }
+
+ return anyUpdates;
+ }
+
+ /**
+ * Adds next SSRC group information update request to
+ * {@link RequestType#CHANNEL_INFO_UPDATE} query currently being built.
+ *
+ * @param ssrcGroupMap the map of content name to the list of
+ * <tt>SourceGroupPacketExtension</tt>.
+ * @param localChannelsInfo {@link ColibriConferenceIQ} holding info about
+ * Colibri channels to be updated.
+ *
+ * @return <tt>true</tt> if the request yields any changes in Colibri
+ * channels state on the bridge or <tt>false</tt> otherwise.
+ * In general when <tt>false</tt> is returned for all
+ * combined requests it makes no sense to send it.
+ */
+ public boolean addSSSRCGroupsInfo(
+ Map<String, List<SourceGroupPacketExtension>> ssrcGroupMap,
+ ColibriConferenceIQ localChannelsInfo)
+ {
+ Objects.requireNonNull(ssrcGroupMap, "ssrcGroupMap");
+ Objects.requireNonNull(localChannelsInfo, "localChannelsInfo");
+
+ if (conferenceState == null
+ || StringUtils.isNullOrEmpty(conferenceState.getID()))
+ {
+ // We are not initialized yet
+ return false;
+ }
+
+ assertRequestType(RequestType.CHANNEL_INFO_UPDATE);
+
+ request.setType(IQ.Type.SET);
+
+ boolean anyUpdates = false;
+
+ // Go over SSRC groups
+ for (String contentName : ssrcGroupMap.keySet())
+ {
+ // Get channel from local channel info
+ ColibriConferenceIQ.Channel rtpChannel
+ = getRtpChannel(localChannelsInfo, contentName);
+ if (rtpChannel == null)
+ {
+ // There's no channel for this content name in localChannelsInfo
+ continue;
+ }
+
+ List<SourceGroupPacketExtension> groups
+ = ssrcGroupMap.get(contentName);
+
+ // Ok we have channel for this content, let's add SSRCs
+ ColibriConferenceIQ.Channel reqChannel
+ = (ColibriConferenceIQ.Channel) getRequestChannel(
+ request.getOrCreateContent(contentName), rtpChannel);
+
+ if (groups.isEmpty() && "video".equalsIgnoreCase(contentName))
+ {
+ anyUpdates = true;
+
+ // Put empty source group to turn off simulcast layers
+ reqChannel.addSourceGroup(
+ SourceGroupPacketExtension.createSimulcastGroup());
+ }
+
+ for (SourceGroupPacketExtension group : groups)
+ {
+ anyUpdates = true;
+
+ reqChannel.addSourceGroup(group);
+ }
+ }
+
+ return anyUpdates;
+ }
+
+ /**
+ * Adds next ICE transport update request to
+ * {@link RequestType#CHANNEL_INFO_UPDATE} query currently being built.
+ *
+ * @param map the map of content name to transport extensions. Maps
+ * transport to media types.
+ * @param localChannelsInfo {@link ColibriConferenceIQ} holding info about
+ * Colibri channels to be updated.
+ *
+ * @return <tt>true</tt> if the request yields any changes in Colibri
+ * channels state on the bridge or <tt>false</tt> otherwise.
+ * In general when <tt>false</tt> is returned for all
+ * combined requests it makes no sense to send it.
+ */
+ public boolean addTransportUpdateReq(
+ Map<String, IceUdpTransportPacketExtension> map,
+ ColibriConferenceIQ localChannelsInfo)
+ {
+ Objects.requireNonNull(map, "map");
+ Objects.requireNonNull(localChannelsInfo, "localChannelsInfo");
+
+ if (conferenceState == null
+ || StringUtils.isNullOrEmpty(conferenceState.getID()))
+ {
+ // We are not initialized yet
+ return false;
+ }
+
+ boolean hasAnyChanges = false;
+
+ assertRequestType(RequestType.CHANNEL_INFO_UPDATE);
+
+ request.setType(IQ.Type.SET);
+
+ for (Map.Entry<String,IceUdpTransportPacketExtension> e
+ : map.entrySet())
+ {
+ String contentName = e.getKey();
+ ColibriConferenceIQ.ChannelCommon channel
+ = getColibriChannel(localChannelsInfo, contentName);
+
+ if (channel != null)
+ {
+ IceUdpTransportPacketExtension transport
+ = IceUdpTransportPacketExtension
+ .cloneTransportAndCandidates(e.getValue(), true);
+
+ ColibriConferenceIQ.ChannelCommon channelRequest
+ = channel instanceof ColibriConferenceIQ.Channel
+ ? new ColibriConferenceIQ.Channel()
+ : new ColibriConferenceIQ.SctpConnection();
+
+ channelRequest.setID(channel.getID());
+ channelRequest.setEndpoint(channel.getEndpoint());
+ channelRequest.setTransport(transport);
+
+ request.getOrCreateContent(contentName)
+ .addChannelCommon(channelRequest);
+
+ hasAnyChanges = true;
+ }
+ }
+ return hasAnyChanges;
}
/**
@@ -583,10 +842,12 @@ public class ColibriBuilder
request.setTo(videobridge);
- if (requestType == RequestType.EXPIRE_CHANNELS
- && !hasAnyChannelsToExpire)
+ if (requestType == RequestType.EXPIRE_CHANNELS)
{
- return null;
+ if (!hasAnyChannelsToExpire)
+ return null;
+
+ hasAnyChannelsToExpire = false;
}
return request;
@@ -720,6 +981,28 @@ public class ColibriBuilder
}
/**
+ * Returns an <tt>Integer</tt> which stands for the audio packet delay
+ * that will be set on all created audio channels or <tt>null</tt> if
+ * the builder should leave not include the XML attribute at all.
+ */
+ public Integer getAudioPacketDelay()
+ {
+ return audioPacketDelay;
+ }
+
+ /**
+ * Configures audio channels packet delay.
+ * @param audioPacketDelay an <tt>Integer</tt> value which stands for
+ * the audio packet delay that will be set on all created audio channels or
+ * <tt>null</tt> if the builder should not set that channel property to any
+ * value.
+ */
+ public void setAudioPacketDelay(Integer audioPacketDelay)
+ {
+ this.audioPacketDelay = audioPacketDelay;
+ }
+
+ /**
* Sets channel 'simulcast-mode' option that will be added to the
* request when channels are created.
* @param simulcastMode a <tt>SimulcastMode</tt> value to specify
@@ -732,69 +1015,64 @@ public class ColibriBuilder
}
/**
- * Adds next payload type information update request to
- * {@link RequestType#RTP_DESCRIPTION_UPDATE} query currently being built.
+ * Creates a new instance of <tt>localChannelInfo</tt> and initializes only
+ * the fields required to identify particular Colibri channel on the bridge.
+ * This instance is meant to be used in Colibri
+ * {@link RequestType#CHANNEL_INFO_UPDATE} requests. This instance is also
+ * added to given <tt>requestContent</tt> which used to construct current
+ * request.
*
- * @param map the map of content name to RTP description packet extension.
- * @param localChannelsInfo {@link ColibriConferenceIQ} holding info about
- * Colibri channels to be updated.
+ * @param requestContent <tt>Content</tt> of Colibri update request to which
+ * new instance wil be automatically added after has been created.
+ * @param localChannelInfo the original channel for which "update request"
+ * equivalent is to be created with this call.
*
- * @return this instance for calls chaining purpose.
+ * @return new instance of <tt>localChannelInfo</tt> and initialized with
+ * only those fields required to identify particular Colibri channel on
+ * the bridge.
*/
- public ColibriBuilder addRtpDescription(
- Map<String, RtpDescriptionPacketExtension> map,
- ColibriConferenceIQ localChannelsInfo) {
-
- if (conferenceState == null
- || StringUtils.isNullOrEmpty(conferenceState.getID()))
- {
- // We are not initialized yet
- return null;
- }
-
- assertRequestType(RequestType.RTP_DESCRIPTION_UPDATE);
-
- request.setType(IQ.Type.SET);
-
- for (Map.Entry<String, RtpDescriptionPacketExtension> e
- : map.entrySet())
+ private ColibriConferenceIQ.ChannelCommon getRequestChannel(
+ ColibriConferenceIQ.Content requestContent,
+ ColibriConferenceIQ.ChannelCommon localChannelInfo)
+ {
+ ColibriConferenceIQ.ChannelCommon reqChannel
+ = requestContent.getChannel(localChannelInfo.getID());
+ if (reqChannel == null)
{
- String contentName = e.getKey();
- ColibriConferenceIQ.ChannelCommon channel
- = getColibriChannel(localChannelsInfo, contentName);
-
- if (channel != null
- && channel instanceof ColibriConferenceIQ.Channel)
+ if (localChannelInfo instanceof ColibriConferenceIQ.Channel)
{
- RtpDescriptionPacketExtension rtpPE = e.getValue();
- if (rtpPE == null)
- {
- continue;
- }
-
- List<PayloadTypePacketExtension> pts = rtpPE.getPayloadTypes();
- if (pts == null || pts.isEmpty())
- {
- continue;
- }
-
- ColibriConferenceIQ.Channel channelRequest
- = new ColibriConferenceIQ.Channel();
+ reqChannel = new ColibriConferenceIQ.Channel();
+ }
+ else if (
+ localChannelInfo instanceof ColibriConferenceIQ.SctpConnection)
+ {
+ reqChannel = new ColibriConferenceIQ.SctpConnection();
+ }
+ else
+ {
+ throw new RuntimeException(
+ "Unsupported ChannelCommon class: "
+ + localChannelInfo.getClass());
+ }
- channelRequest.setID(channel.getID());
+ reqChannel.setID(localChannelInfo.getID());
- for (PayloadTypePacketExtension ptPE : rtpPE.getPayloadTypes())
- {
- channelRequest.addPayloadType(ptPE);
- }
+ requestContent.addChannelCommon(reqChannel);
+ }
+ return reqChannel;
+ }
- request.getOrCreateContent(contentName)
- .addChannel(channelRequest);
- }
+ private ColibriConferenceIQ.Channel getRtpChannel(
+ ColibriConferenceIQ localChannelsInfo,
+ String contentName)
+ {
+ ColibriConferenceIQ.Content content
+ = localChannelsInfo.getContent(contentName);
- }
+ if (content == null)
+ return null;
- return this;
+ return content.getChannelCount() > 0 ? content.getChannel(0) : null;
}
/**
@@ -808,19 +1086,10 @@ public class ColibriBuilder
ALLOCATE_CHANNELS,
/**
- * Updates transport information for channels that use RTP bundle.
- */
- BUNDLE_TRANSPORT_UPDATE,
-
- /**
- * Updates channel transport information(ICE transport candidates).
+ * An update request which is meant to modify some values of existing
+ * Colibri channels on the bridge.
*/
- TRANSPORT_UPDATE,
-
- /**
- * Updates the RTP description of a channel (payload types).
- */
- RTP_DESCRIPTION_UPDATE,
+ CHANNEL_INFO_UPDATE,
/**
* Expires specified Colibri channels.
@@ -833,4 +1102,28 @@ public class ColibriBuilder
*/
UNDEFINED;
}
+
+ /**
+ * Configures RTP-level relay (RFC 3550, section 2.3).
+ * @param rtpLevelRelayType an <tt>RTPLevelRelayType</tt> value which
+ * stands for the rtp level relay type that will be set on all created
+ * audio channels.
+ */
+ public void setRTPLevelRelayType(RTPLevelRelayType rtpLevelRelayType)
+ {
+ this.rtpLevelRelayType = rtpLevelRelayType;
+ }
+
+ /**
+ * Configures RTP-level relay (RFC 3550, section 2.3).
+ * @param rtpLevelRelayType a <tt>String</tt> value which
+ * stands for the rtp level relay type that will be set on all created
+ * audio channels.
+ */
+ public void setRTPLevelRelayType(String rtpLevelRelayType)
+ {
+ setRTPLevelRelayType
+ (RTPLevelRelayType.parseRTPLevelRelayType(rtpLevelRelayType));
+ }
+
}