diff --git a/lib/installer-exclude/fmj.jar b/lib/installer-exclude/fmj.jar
index 699a8930d..a4133b8f0 100644
Binary files a/lib/installer-exclude/fmj.jar and b/lib/installer-exclude/fmj.jar differ
diff --git a/lib/installer-exclude/libjitsi.jar b/lib/installer-exclude/libjitsi.jar
index 9a9aa1106..48d4ab582 100644
Binary files a/lib/installer-exclude/libjitsi.jar and b/lib/installer-exclude/libjitsi.jar differ
diff --git a/resources/install/README.Debian b/resources/install/README.Debian
index ecd925b20..f75ea2891 100644
--- a/resources/install/README.Debian
+++ b/resources/install/README.Debian
@@ -2,6 +2,7 @@ To create debian source package you need some other projects sources that
jitsi depends on. In the same folder where jitsi is checked out do:
git clone https://github.com/jitsi/otr4j.git
git clone https://github.com/jitsi/libsrc.git
+svn checkout http://irc-api.googlecode.com/svn/trunk/ irc-api
And then in jitsi do: ant deb-src -Dlabel=4444
This will create orig.tar.gz debian sources that can be used to debuild
debian package.
\ No newline at end of file
diff --git a/resources/install/build.xml b/resources/install/build.xml
index 57b8e11cc..9e9cacd82 100644
--- a/resources/install/build.xml
+++ b/resources/install/build.xml
@@ -2458,9 +2458,6 @@
and libsrc
-->
-
-
@@ -2524,6 +2521,14 @@
+
+
+
+
+
+
+
+
@@ -2658,26 +2663,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -2898,7 +2884,8 @@
-
@@ -2908,6 +2895,68 @@
overwrite="true"
link="${debian.src.dir}/lib/installer-exclude"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
reference:file:/usr/share/jitsi-common/ui-service.jar
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/install/debian/control-src.tmpl b/resources/install/debian/control-src.tmpl
index 4963ab4db..cd1b674e2 100644
--- a/resources/install/debian/control-src.tmpl
+++ b/resources/install/debian/control-src.tmpl
@@ -48,7 +48,9 @@ Build-Depends: debhelper (>= 9), javahelper,
glassfish-activation,
glassfish-mail,
libbcpkix-java,
- libjcalendar-java
+ libjcalendar-java,
+ libphonenumber6-java,
+ libslf4j-java
Standards-Version: 3.9.5
Package: _PACKAGE_NAME_
@@ -80,7 +82,9 @@ Depends: ${misc:Depends},
libguava-java,
libhsqldb-java,
libjson-simple-java (>= 1.1.1),
- libjcalendar-java
+ libjcalendar-java,
+ libphonenumber6-java,
+ libslf4j-java
Recommends: ${java:Recommends}
Description: VoIP and Instant Messaging client
_APP_NAME_ is an application that allows you to do audio/video
diff --git a/resources/install/debian/rules.tmpl b/resources/install/debian/rules.tmpl
index a960b7d37..eeec3b6fe 100755
--- a/resources/install/debian/rules.tmpl
+++ b/resources/install/debian/rules.tmpl
@@ -21,7 +21,7 @@ override_dh_install-indep:
# make and install the debian specific bundles
# use the prebuild and installed bundles to extract/modify and use the
# exising debian java packages
- $(ANT) -file build.xml -Ddebian.bundles.dest=debian/$(PACKAGE_NAME)/usr/share/$(PACKAGE_NAME)/sc-bundles -Ddebian.bundles.common.dest=debian/$(PACKAGE_NAME)-common/usr/share/$(PACKAGE_NAME)-common deb-bundle-jna deb-bundle-util deb-bundle-sysactivitynotifications deb-bundle-swing-ui deb-bundle-json deb-bundle-smacklib deb-bundle-jmdnslib deb-bundle-desktoputil deb-bundle-bouncycastle deb-bundle-plugin-accountinfo deb-bundle-commons-lang deb-bundle-hsqldb deb-libjitsi-deps deb-bundle-httpmime deb-bundle-common
+ $(ANT) -file build.xml -Ddebian.bundles.dest=debian/$(PACKAGE_NAME)/usr/share/$(PACKAGE_NAME)/sc-bundles -Ddebian.bundles.common.dest=debian/$(PACKAGE_NAME)-common/usr/share/$(PACKAGE_NAME)-common deb-bundle-jna deb-bundle-util deb-bundle-sysactivitynotifications deb-bundle-swing-ui deb-bundle-json deb-bundle-smacklib deb-bundle-jmdnslib deb-bundle-desktoputil deb-bundle-bouncycastle deb-bundle-plugin-accountinfo deb-bundle-commons-lang deb-bundle-hsqldb deb-libjitsi-deps deb-bundle-httpmime deb-bundle-common deb-bundle-slf4j
override_dh_install-arch:
ifeq ($(DEB_HOST_ARCH),amd64)
diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatRoomAutoOpenConfigDialog.java b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatRoomAutoOpenConfigDialog.java
index 410ce7b15..88cb77d11 100644
--- a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatRoomAutoOpenConfigDialog.java
+++ b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatRoomAutoOpenConfigDialog.java
@@ -228,7 +228,7 @@ private void refreshValue()
propertyListener);
if(value == null)
- value = MUCService.OPEN_ON_IMPORTANT_MESSAGE;
+ value = MUCService.DEFAULT_AUTO_OPEN_BEHAVIOUR;
if(value.equals(MUCService.OPEN_ON_ACTIVITY))
{
diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatManager.java b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatManager.java
index a7643eb22..b4f2abd7b 100644
--- a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatManager.java
+++ b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatManager.java
@@ -24,9 +24,8 @@
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.Logger;
-import org.jitsi.util.*;
-
import org.jdesktop.swingworker.SwingWorker;
+import org.jitsi.util.*;
import org.osgi.framework.*;
/**
@@ -214,7 +213,7 @@ public void messageReceived(ChatRoomMessageReceivedEvent evt)
sourceChatRoom.getParentProvider(),
sourceChatRoom.getIdentifier());
if(autoOpenConfig == null)
- autoOpenConfig = MUCService.OPEN_ON_IMPORTANT_MESSAGE;
+ autoOpenConfig = MUCService.DEFAULT_AUTO_OPEN_BEHAVIOUR;
if(autoOpenConfig.equals(MUCService.OPEN_ON_ACTIVITY)
|| (autoOpenConfig.equals(MUCService.OPEN_ON_MESSAGE)
@@ -307,7 +306,7 @@ else if(o instanceof ChatRoomMessageReceivedEvent)
null);
if(createWindow)
- chatWindowManager.openChat(chatPanel, true);
+ chatWindowManager.openChat(chatPanel, false);
}
/**
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/SourceContactRightButtonMenu.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/SourceContactRightButtonMenu.java
index d622ba4f3..06d5705ed 100644
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/SourceContactRightButtonMenu.java
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/SourceContactRightButtonMenu.java
@@ -89,11 +89,11 @@ private void initItems()
.getPreferredContactDetail(OperationSetBasicTelephony.class);
// Call menu.
- if (cDetail != null
- && sourceContact.getContactSource().getType()
- != ContactSourceService.RECENT_MESSAGES_TYPE)
+ if (cDetail != null)
{
- add(initCallMenu());
+ Component c = initCallMenu();
+ if(c != null)
+ add(c);
}
// Only create the menu if the add contact functionality is enabled.
@@ -181,6 +181,10 @@ else if (providersCount > 1)
contains(OperationSetBasicTelephony.class));
callContactMenu.add(callContactItem);
}
+
+ if(callContactMenu.getMenuComponentCount() == 0)
+ return null;
+
return callContactMenu;
}
diff --git a/src/net/java/sip/communicator/impl/msghistory/MessageHistoryServiceImpl.java b/src/net/java/sip/communicator/impl/msghistory/MessageHistoryServiceImpl.java
index c6ed3cc6b..5ff97c385 100644
--- a/src/net/java/sip/communicator/impl/msghistory/MessageHistoryServiceImpl.java
+++ b/src/net/java/sip/communicator/impl/msghistory/MessageHistoryServiceImpl.java
@@ -1139,6 +1139,8 @@ private void loadRecentMessages()
messageSourceServiceReg = bundleContext.registerService(
ContactSourceService.class.getName(),
messageSourceService, null);
+ MessageHistoryActivator.getContactListService()
+ .addMetaContactListListener(this.messageSourceService);
}
/**
@@ -1148,6 +1150,9 @@ private void stopRecentMessages()
{
if(messageSourceServiceReg != null)
{
+ MessageHistoryActivator.getContactListService()
+ .removeMetaContactListListener(this.messageSourceService);
+
messageSourceServiceReg.unregister();
messageSourceServiceReg = null;
diff --git a/src/net/java/sip/communicator/impl/msghistory/MessageSourceContact.java b/src/net/java/sip/communicator/impl/msghistory/MessageSourceContact.java
index dcb43a1f9..9031cbdff 100644
--- a/src/net/java/sip/communicator/impl/msghistory/MessageSourceContact.java
+++ b/src/net/java/sip/communicator/impl/msghistory/MessageSourceContact.java
@@ -6,6 +6,7 @@
*/
package net.java.sip.communicator.impl.msghistory;
+import net.java.sip.communicator.service.contactlist.*;
import net.java.sip.communicator.service.contactsource.*;
import net.java.sip.communicator.service.msghistory.*;
import net.java.sip.communicator.service.muc.*;
@@ -175,7 +176,7 @@ void update(EventObject source)
this.contact = e.getDestinationContact();
this.address = contact.getAddress();
- this.displayName = contact.getDisplayName();
+ this.updateDisplayName();
this.ppService = contact.getProtocolProvider();
this.image = contact.getImage();
this.status = contact.getPresenceStatus();
@@ -189,7 +190,7 @@ else if(source instanceof MessageReceivedEvent)
this.contact = e.getSourceContact();
this.address = contact.getAddress();
- this.displayName = contact.getDisplayName();
+ this.updateDisplayName();
this.ppService = contact.getProtocolProvider();
this.image = contact.getImage();
this.status = contact.getPresenceStatus();
@@ -279,6 +280,9 @@ else if(source instanceof ChatRoomMessageDeliveredEvent
*/
void initDetails(boolean isChatRoom, Contact contact)
{
+ if(!isChatRoom && contact != null)
+ this.updateDisplayName();
+
ContactDetail contactDetail =
new ContactDetail(
this.address,
@@ -334,6 +338,7 @@ void initDetails(boolean isChatRoom, Contact contact)
contactDetail.setSupportedOpSets(supportedOpSets);
}
+ contactDetails.clear();
contactDetails.add(contactDetail);
}
@@ -506,6 +511,24 @@ public void setDisplayName(String displayName)
this.displayName = displayName;
}
+ /**
+ * Updates display name if contact is not null.
+ */
+ private void updateDisplayName()
+ {
+ if(this.contact == null)
+ return;
+
+ MetaContact metaContact
+ = MessageHistoryActivator.getContactListService()
+ .findMetaContactByContact(contact);
+
+ if(metaContact == null)
+ return;
+
+ this.displayName = metaContact.getDisplayName();
+ }
+
/**
* Compares two MessageSourceContacts.
* @param o the object to compare with
diff --git a/src/net/java/sip/communicator/impl/msghistory/MessageSourceContactQuery.java b/src/net/java/sip/communicator/impl/msghistory/MessageSourceContactQuery.java
new file mode 100644
index 000000000..6e0d6049a
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/msghistory/MessageSourceContactQuery.java
@@ -0,0 +1,241 @@
+/*
+ * Jitsi, 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.msghistory;
+
+import net.java.sip.communicator.service.contactsource.*;
+import net.java.sip.communicator.service.protocol.*;
+
+import java.util.*;
+import java.util.regex.*;
+
+/**
+ * The query which creates source contacts and uses the values stored in
+ * MessageSourceService.
+ *
+ * @author Damian Minkov
+ */
+public class MessageSourceContactQuery
+ extends AsyncContactQuery
+{
+ /**
+ * Constructs.
+ *
+ * @param messageSourceService
+ */
+ MessageSourceContactQuery(MessageSourceService messageSourceService)
+ {
+ super(messageSourceService,
+ Pattern.compile("",
+ Pattern.CASE_INSENSITIVE | Pattern.LITERAL),
+ false);
+ }
+
+ /**
+ * Creates MessageSourceContact for all currently cached
+ * recent messages in the MessageSourceService.
+ */
+ @Override
+ public void run()
+ {
+ getContactSource().updateRecentMessages();
+ }
+
+ /**
+ * Updates capabilities from EventObject for the found
+ * MessageSourceContact equals to the Object supplied.
+ * Note that Object may not be MessageSourceContact, but its
+ * equals method can return true for message source contact instances.
+ * @param srcObj used to search for MessageSourceContact
+ * @param eventObj the values used for the update
+ */
+ public void updateCapabilities(Object srcObj, EventObject eventObj)
+ {
+ for(SourceContact msc : getQueryResults())
+ {
+ if(srcObj.equals(msc)
+ && msc instanceof MessageSourceContact)
+ {
+ ((MessageSourceContact)msc).initDetails(eventObj);
+
+ break;
+ }
+ }
+ }
+
+ /**
+ * Updates capabilities from Contact for the found
+ * MessageSourceContact equals to the Object supplied.
+ * Note that Object may not be MessageSourceContact, but its
+ * equals method can return true for message source contact instances.
+ * @param srcObj used to search for MessageSourceContact
+ * @param contact the values used for the update
+ */
+ public void updateCapabilities(Object srcObj, Contact contact)
+ {
+ for(SourceContact msc : getQueryResults())
+ {
+ if(srcObj.equals(msc)
+ && msc instanceof MessageSourceContact)
+ {
+ ((MessageSourceContact)msc).initDetails(false, contact);
+
+ break;
+ }
+ }
+ }
+
+ /**
+ * Notifies the ContactQueryListeners registered with this
+ * ContactQuery that a SourceContact has been
+ * changed.
+ * Note that Object may not be MessageSourceContact, but its
+ * equals method can return true for message source contact instances.
+ *
+ * @param srcObj the Object representing a recent message
+ * which has been changed and corresponding SourceContact
+ * which the registered ContactQueryListeners are to be
+ * notified about
+ */
+ public void updateContact(Object srcObj, EventObject eventObject)
+ {
+ for(SourceContact msc : getQueryResults())
+ {
+ if(srcObj.equals(msc)
+ && msc instanceof MessageSourceContact)
+ {
+ ((MessageSourceContact)msc).update(eventObject);
+
+ super.fireContactChanged(msc);
+
+ break;
+ }
+ }
+ }
+
+ /**
+ * Notifies the ContactQueryListeners registered with this
+ * ContactQuery that a SourceContact has been
+ * changed.
+ * Note that Object may not be MessageSourceContact, but its
+ * equals method can return true for message source contact instances.
+ *
+ * @param srcObj the Object representing a recent message
+ * which has been changed and corresponding SourceContact
+ * which the registered ContactQueryListeners are to be
+ * notified about
+ */
+ public void fireContactChanged(Object srcObj)
+ {
+ for(SourceContact msc : getQueryResults())
+ {
+ if(srcObj.equals(msc)
+ && msc instanceof MessageSourceContact)
+ {
+ super.fireContactChanged(msc);
+
+ break;
+ }
+ }
+ }
+
+ /**
+ * Notifies the ContactQueryListeners registered with this
+ * ContactQuery that a SourceContact has been
+ * changed.
+ * Note that Object may not be MessageSourceContact, but its
+ * equals method can return true for message source contact instances.
+ *
+ * @param srcObj the Object representing a recent message
+ * which has been changed and corresponding SourceContact
+ * which the registered ContactQueryListeners are to be
+ * notified about
+ */
+ public void updateContactStatus(Object srcObj,
+ PresenceStatus status)
+ {
+ for(SourceContact msc : getQueryResults())
+ {
+ if(srcObj.equals(msc)
+ && msc instanceof MessageSourceContact)
+ {
+ ((MessageSourceContact)msc).setStatus(status);
+
+ super.fireContactChanged(msc);
+
+ break;
+ }
+ }
+ }
+
+ /**
+ * Notifies the ContactQueryListeners registered with this
+ * ContactQuery that a SourceContact has been
+ * changed.
+ * Note that Object may not be MessageSourceContact, but its
+ * equals method can return true for message source contact instances.
+ *
+ * @param srcObj the Object representing a recent message
+ * which has been changed and corresponding SourceContact
+ * which the registered ContactQueryListeners are to be
+ * notified about
+ */
+ public void updateContactDisplayName(Object srcObj,
+ String newName)
+ {
+ for(SourceContact msc : getQueryResults())
+ {
+ if(srcObj.equals(msc)
+ && msc instanceof MessageSourceContact)
+ {
+ ((MessageSourceContact)msc).setDisplayName(newName);
+
+ super.fireContactChanged(msc);
+
+ break;
+ }
+ }
+ }
+
+ /**
+ * Notifies the ContactQueryListeners registered with this
+ * ContactQuery that a SourceContact has been
+ * removed.
+ * Note that Object may not be MessageSourceContact, but its
+ * equals method can return true for message source contact instances.
+ *
+ * @param srcObj representing the message and its corresponding
+ * SourceContact which has been removed and which the registered
+ * ContactQueryListeners are to be notified about
+ */
+ public void fireContactRemoved(Object srcObj)
+ {
+ for(SourceContact msc : getQueryResults())
+ {
+ if(srcObj.equals(msc))
+ {
+ super.fireContactRemoved(msc);
+
+ break;
+ }
+ }
+ }
+
+ /**
+ * Adds a specific SourceContact to the list of
+ * SourceContacts to be returned by this ContactQuery in
+ * response to {@link #getQueryResults()}.
+ *
+ * @param sourceContact the SourceContact to be added to the
+ * queryResults of this ContactQuery
+ * @return true if the queryResults of this
+ * ContactQuery has changed in response to the call
+ */
+ public boolean addQueryResult(SourceContact sourceContact)
+ {
+ return super.addQueryResult(sourceContact, false);
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/msghistory/MessageSourceService.java b/src/net/java/sip/communicator/impl/msghistory/MessageSourceService.java
index 8e0cb70e9..15d104bd1 100644
--- a/src/net/java/sip/communicator/impl/msghistory/MessageSourceService.java
+++ b/src/net/java/sip/communicator/impl/msghistory/MessageSourceService.java
@@ -13,6 +13,7 @@
import java.util.regex.*;
import net.java.sip.communicator.service.contactlist.*;
+import net.java.sip.communicator.service.contactlist.event.*;
import net.java.sip.communicator.service.contactsource.*;
import net.java.sip.communicator.service.history.*;
import net.java.sip.communicator.service.history.records.*;
@@ -32,6 +33,7 @@
* @author Damian Minkov
*/
public class MessageSourceService
+ extends MetaContactListAdapter
implements ContactSourceService,
ContactPresenceStatusListener,
ContactCapabilitiesListener,
@@ -126,8 +128,8 @@ public class MessageSourceService
/**
* List of recent messages.
*/
- private List recentMessages
- = new LinkedList();
+ private final List recentMessages
+ = new LinkedList();
/**
* Date of the oldest shown message.
@@ -137,7 +139,7 @@ public class MessageSourceService
/**
* The last query created.
*/
- private MessageHistoryContactQuery recentQuery = null;
+ private MessageSourceContactQuery recentQuery = null;
/**
* The message subtype if any.
@@ -223,19 +225,54 @@ public int getIndex()
public ContactQuery createContactQuery(String queryString)
{
recentQuery =
- (MessageHistoryContactQuery)createContactQuery(
+ (MessageSourceContactQuery)createContactQuery(
queryString, numberOfMessages);
return recentQuery;
}
+ /**
+ * Updates the contact sources in the recent query if any.
+ * Done here in order to sync with recentMessages instance, and to
+ * check for already existing instances of contact sources.
+ * Normally called from the query.
+ */
+ public void updateRecentMessages()
+ {
+ if(recentQuery == null)
+ return;
+
+ synchronized(recentMessages)
+ {
+ List currentContactsInQuery
+ = recentQuery.getQueryResults();
+
+ for(ComparableEvtObj evtObj : recentMessages)
+ {
+ // the contains will use the correct equals method of
+ // the object evtObj
+ if(!currentContactsInQuery.contains(evtObj))
+ {
+ MessageSourceContact newSourceContact =
+ new MessageSourceContact(
+ evtObj.getEventObject(),
+ MessageSourceService.this);
+ newSourceContact.initDetails(evtObj.getEventObject());
+
+ recentQuery.addQueryResult(newSourceContact);
+ }
+ }
+ }
+ }
+
/**
* Searches for entries in cached recent messages in history.
*
- * @param provider
- * @return
+ * @param provider the provider which contact messages we will search
+ * @param isStatusChanged is the search because of status changed
+ * @return entries in cached recent messages in history.
*/
- private List getSourceContacts(
+ private List getCachedRecentMessages(
ProtocolProviderService provider, boolean isStatusChanged)
{
String providerID = provider.getAccountID().getAccountUniqueID();
@@ -244,8 +281,8 @@ private List getSourceContacts(
recentMessages.size() < numberOfMessages
? null : oldestRecentMessage );
- List sourceContactsToAdd
- = new ArrayList();
+ List cachedRecentMessages
+ = new ArrayList();
for(String contactID : recentMessagesContactIDs)
{
@@ -256,10 +293,10 @@ private List getSourceContacts(
contactID,
isSMSEnabled);
- processEventObjects(res, sourceContactsToAdd, isStatusChanged);
+ processEventObjects(res, cachedRecentMessages, isStatusChanged);
}
- return sourceContactsToAdd;
+ return cachedRecentMessages;
}
/**
@@ -273,46 +310,46 @@ private List getSourceContacts(
* If nothing found a new contact is created.
*
* @param res list of event
- * @param sourceContactsToAdd list of newly created source contacts
+ * @param cachedRecentMessages list of newly created source contacts
* or already existed but updated with corresponding event object
* @param isStatusChanged whether provider status changed
* and we are processing
*/
private void processEventObjects(
Collection res,
- List sourceContactsToAdd,
+ List cachedRecentMessages,
boolean isStatusChanged)
{
for(EventObject obj : res)
{
- MessageSourceContact msc =
- findMessageSourceContact(obj, recentMessages);
+ ComparableEvtObj oldMsg = findRecentMessage(obj, recentMessages);
- if(msc != null)
+ if(oldMsg != null)
{
- msc.update(obj);// update
+ oldMsg.update(obj);// update
- if(isStatusChanged)
- msc.initDetails(obj);// update capabilities
+ if(isStatusChanged && recentQuery != null)
+ recentQuery.updateCapabilities(oldMsg, obj);
- // we still add it to sourceContactsToAdd
+ // we still add it to cachedRecentMessages
// later we will find it is duplicate and will fire
// update event
- if(!sourceContactsToAdd.contains(msc))
- sourceContactsToAdd.add(msc);
+ if(!cachedRecentMessages.contains(oldMsg))
+ cachedRecentMessages.add(oldMsg);
continue;
}
- msc = findMessageSourceContact(obj, sourceContactsToAdd);
+ oldMsg = findRecentMessage(obj, cachedRecentMessages);
- if(msc == null)
+ if(oldMsg == null)
{
- msc = new MessageSourceContact(
- obj, MessageSourceService.this);
- if(isStatusChanged)
- msc.initDetails(obj);
- sourceContactsToAdd.add(msc);
+ oldMsg = new ComparableEvtObj(obj);
+
+ if(isStatusChanged && recentQuery != null)
+ recentQuery.updateCapabilities(oldMsg, obj);
+
+ cachedRecentMessages.add(oldMsg);
}
}
}
@@ -327,64 +364,52 @@ boolean isSMSEnabled()
}
/**
- * Add the source contacts, newly added will fire new,
+ * Add the ComparableEvtObj, newly added will fire new,
* for existing fire update and when trimming the list to desired length
* fire remove for those that were removed
* @param contactsToAdd
*/
- private void addNewRecentMessages(List contactsToAdd)
+ private void addNewRecentMessages(
+ List contactsToAdd)
{
// now find object to fire new, and object to fire remove
// let us find duplicates and fire update
- List duplicates
- = new ArrayList();
- for(MessageSourceContact msc : recentMessages)
+ List duplicates = new ArrayList();
+ for(ComparableEvtObj msgToAdd : contactsToAdd)
{
- for(MessageSourceContact mscToAdd : contactsToAdd)
+ if(recentMessages.contains(msgToAdd))
{
- if(mscToAdd.equals(msc))
- {
- duplicates.add(msc);
+ duplicates.add(msgToAdd);
- // update currently used instance
- //msc.update(mscToAdd);
- // it was already updated
-
- // save update
- updateRecentMessageToHistory(msc);
- }
+ // save update
+ updateRecentMessageToHistory(msgToAdd);
}
}
+ recentMessages.removeAll(duplicates);
- if(!duplicates.isEmpty())
- {
- contactsToAdd.removeAll(duplicates);
+ // now contacts to add has no duplicates, add them all
+ boolean changed = recentMessages.addAll(contactsToAdd);
+ if(changed)
+ {
Collections.sort(recentMessages);
if(recentQuery != null)
{
- for(MessageSourceContact msc : duplicates)
- recentQuery.fireContactChanged(msc);
+ for(ComparableEvtObj obj : duplicates)
+ recentQuery.updateContact(obj, obj.getEventObject());
}
-
- return;
}
- // now contacts to add has no duplicates, add them all
- recentMessages.addAll(contactsToAdd);
-
- Collections.sort(recentMessages);
-
if(!recentMessages.isEmpty())
oldestRecentMessage
= recentMessages.get(recentMessages.size() - 1).getTimestamp();
// trim
- List removedItems = null;
+ List removedItems = null;
if(recentMessages.size() > numberOfMessages)
{
- removedItems = new ArrayList(
+ removedItems = new ArrayList(
recentMessages.subList(numberOfMessages, recentMessages.size()));
recentMessages.removeAll(removedItems);
@@ -396,7 +421,7 @@ private void addNewRecentMessages(List contactsToAdd)
// and now are removed after trim
if(removedItems != null)
{
- for(MessageSourceContact msc : removedItems)
+ for(ComparableEvtObj msc : removedItems)
{
if(!contactsToAdd.contains(msc))
recentQuery.fireContactRemoved(msc);
@@ -404,12 +429,28 @@ private void addNewRecentMessages(List contactsToAdd)
}
// fire new for all that were added, and not removed after trim
- for(MessageSourceContact msc : contactsToAdd)
+ for(ComparableEvtObj msc : contactsToAdd)
{
- if(removedItems == null
+ if((removedItems == null
|| !removedItems.contains(msc))
- recentQuery.fireContactReceived(msc);
+ && !duplicates.contains(msc))
+ {
+ MessageSourceContact newSourceContact =
+ new MessageSourceContact(
+ msc.getEventObject(),
+ MessageSourceService.this);
+ newSourceContact.initDetails(msc.getEventObject());
+
+ recentQuery.addQueryResult(newSourceContact);
+ }
}
+
+ // if recent messages were changed, indexes have change lets
+ // fire event for the last element which will reorder the whole
+ // group if needed.
+ if(changed)
+ recentQuery.fireContactChanged(
+ recentMessages.get(recentMessages.size() - 1));
}
}
@@ -446,10 +487,10 @@ private void handleProviderAddedInSeparateThread(
synchronized(recentMessages)
{
- List sourceContactsToAdd
- = getSourceContacts(provider, isStatusChanged);
+ List cachedRecentMessages
+ = getCachedRecentMessages(provider, isStatusChanged);
- if(sourceContactsToAdd.isEmpty())
+ if(cachedRecentMessages.isEmpty())
{
// maybe there is no cached history for this
// let's check
@@ -461,33 +502,32 @@ private void handleProviderAddedInSeparateThread(
null,
isSMSEnabled);
- List newMsc
- = new ArrayList();
+ List newMsc
+ = new ArrayList();
processEventObjects(res, newMsc, isStatusChanged);
addNewRecentMessages(newMsc);
- for(MessageSourceContact msc : newMsc)
+ for(ComparableEvtObj msc : newMsc)
{
saveRecentMessageToHistory(msc);
}
-
}
else
- addNewRecentMessages(sourceContactsToAdd);
+ addNewRecentMessages(cachedRecentMessages);
}
}
/**
* Tries to match the event object to already existing
- * MessageSourceContact in the supplied list.
+ * ComparableEvtObj in the supplied list.
* @param obj the object that we will try to match.
* @param list the list we will search in.
- * @return the found source contact
+ * @return the found ComparableEvtObj
*/
- private static MessageSourceContact findMessageSourceContact(
- EventObject obj, List list)
+ private static ComparableEvtObj findRecentMessage(
+ EventObject obj, List list)
{
Contact contact = null;
ChatRoom chatRoom = null;
@@ -509,13 +549,13 @@ else if(obj instanceof ChatRoomMessageReceivedEvent)
chatRoom = ((ChatRoomMessageReceivedEvent)obj).getSourceChatRoom();
}
- for(MessageSourceContact msc : list)
+ for(ComparableEvtObj evt : list)
{
if((contact != null
- && contact.equals(msc.getContact()))
+ && contact.equals(evt.getContact()))
|| (chatRoom != null
- && chatRoom.equals(msc.getRoom())))
- return msc;
+ && chatRoom.equals(evt.getRoom())))
+ return evt;
}
return null;
@@ -534,9 +574,9 @@ void handleProviderRemoved(ProtocolProviderService provider)
{
if(provider != null)
{
- List removedItems
- = new ArrayList();
- for(MessageSourceContact msc : recentMessages)
+ List removedItems
+ = new ArrayList();
+ for(ComparableEvtObj msc : recentMessages)
{
if(msc.getProtocolProviderService().equals(provider))
removedItems.add(msc);
@@ -552,7 +592,7 @@ void handleProviderRemoved(ProtocolProviderService provider)
if(recentQuery != null)
{
- for(MessageSourceContact msc : removedItems)
+ for(ComparableEvtObj msc : removedItems)
{
recentQuery.fireContactRemoved(msc);
}
@@ -561,12 +601,12 @@ void handleProviderRemoved(ProtocolProviderService provider)
// lets do the same as we enable provider
// for all registered providers and finally fire events
- List contactsToAdd
- = new ArrayList();
+ List contactsToAdd
+ = new ArrayList();
for (ProtocolProviderService pps
: messageHistoryService.getCurrentlyAvailableProviders())
{
- contactsToAdd.addAll(getSourceContacts(pps, true));
+ contactsToAdd.addAll(getCachedRecentMessages(pps, true));
}
addNewRecentMessages(contactsToAdd);
@@ -715,7 +755,11 @@ int getIndex(MessageSourceContact messageSourceContact)
{
synchronized(recentMessages)
{
- return recentMessages.indexOf(messageSourceContact);
+ for (int i = 0; i < recentMessages.size(); i++)
+ if(recentMessages.get(i).equals(messageSourceContact))
+ return i;
+
+ return -1;
}
}
@@ -731,7 +775,8 @@ public ContactQuery createContactQuery(String queryString, int contactCount)
if(!StringUtils.isNullOrEmpty(queryString))
return null;
- recentQuery = new MessageHistoryContactQuery(numberOfMessages);
+ recentQuery = new MessageSourceContactQuery(
+ MessageSourceService.this);
return recentQuery;
}
@@ -741,20 +786,20 @@ public ContactQuery createContactQuery(String queryString, int contactCount)
* @param evt the ContactPresenceStatusChangeEvent describing the status
*/
@Override
- public void contactPresenceStatusChanged(ContactPresenceStatusChangeEvent evt)
+ public void contactPresenceStatusChanged(
+ ContactPresenceStatusChangeEvent evt)
{
if(recentQuery == null)
return;
synchronized(recentMessages)
{
- for(MessageSourceContact msgSC : recentMessages)
+ for(ComparableEvtObj msg : recentMessages)
{
- if(msgSC.getContact() != null
- && msgSC.getContact().equals(evt.getSourceContact()))
+ if(msg.getContact() != null
+ && msg.getContact().equals(evt.getSourceContact()))
{
- msgSC.setStatus(evt.getNewStatus());
- recentQuery.fireContactChanged(msgSC);
+ recentQuery.updateContactStatus(msg, evt.getNewStatus());
}
}
}
@@ -780,11 +825,11 @@ public void localUserPresenceChanged(
if(recentQuery == null)
return;
- MessageSourceContact srcContact = null;
+ ComparableEvtObj srcContact = null;
synchronized(recentMessages)
{
- for(MessageSourceContact msg : recentMessages)
+ for(ComparableEvtObj msg : recentMessages)
{
if(msg.getRoom() != null
&& msg.getRoom().equals(evt.getChatRoom()))
@@ -803,8 +848,9 @@ public void localUserPresenceChanged(
if (LocalUserChatRoomPresenceChangeEvent
.LOCAL_USER_JOINED.equals(eventType))
{
- srcContact.setStatus(ChatRoomPresenceStatus.CHAT_ROOM_ONLINE);
- recentQuery.fireContactChanged(srcContact);
+ recentQuery.updateContactStatus(
+ srcContact,
+ ChatRoomPresenceStatus.CHAT_ROOM_ONLINE);
}
else if ((LocalUserChatRoomPresenceChangeEvent
.LOCAL_USER_LEFT.equals(eventType)
@@ -814,8 +860,9 @@ else if ((LocalUserChatRoomPresenceChangeEvent
.LOCAL_USER_DROPPED.equals(eventType))
)
{
- srcContact.setStatus(ChatRoomPresenceStatus.CHAT_ROOM_OFFLINE);
- recentQuery.fireContactChanged(srcContact);
+ recentQuery.updateContactStatus(
+ srcContact,
+ ChatRoomPresenceStatus.CHAT_ROOM_OFFLINE);
}
}
@@ -833,8 +880,8 @@ private void handle(EventObject obj,
// check if provider - contact exist update message content
synchronized(recentMessages)
{
- MessageSourceContact existingMsc = null;
- for(MessageSourceContact msc : recentMessages)
+ ComparableEvtObj existingMsc = null;
+ for(ComparableEvtObj msc : recentMessages)
{
if(msc.getProtocolProviderService().equals(provider)
&& msc.getContactAddress().equals(id))
@@ -865,17 +912,18 @@ private void handle(EventObject obj,
new MessageSourceContact(obj, MessageSourceService.this);
newSourceContact.initDetails(obj);
// we have already checked for duplicate
- recentMessages.add(newSourceContact);
+ ComparableEvtObj newMsg = new ComparableEvtObj(obj);
+ recentMessages.add(newMsg);
Collections.sort(recentMessages);
oldestRecentMessage
= recentMessages.get(recentMessages.size() - 1).getTimestamp();
// trim
- List removedItems = null;
+ List removedItems = null;
if(recentMessages.size() > numberOfMessages)
{
- removedItems = new ArrayList(
+ removedItems = new ArrayList(
recentMessages.subList(
numberOfMessages, recentMessages.size()));
@@ -883,7 +931,7 @@ private void handle(EventObject obj,
}
// save
- saveRecentMessageToHistory(newSourceContact);
+ saveRecentMessageToHistory(newMsg);
// no query nothing to fire
if(recentQuery == null)
@@ -892,20 +940,20 @@ private void handle(EventObject obj,
// now fire
if(removedItems != null)
{
- for(MessageSourceContact msc : removedItems)
+ for(ComparableEvtObj msc : removedItems)
{
recentQuery.fireContactRemoved(msc);
}
}
- recentQuery.fireContactReceived(newSourceContact);
+ recentQuery.addQueryResult(newSourceContact);
}
}
/**
* Adds recent message in history.
*/
- private void saveRecentMessageToHistory(MessageSourceContact msc)
+ private void saveRecentMessageToHistory(ComparableEvtObj msc)
{
synchronized(historyID)
{
@@ -942,7 +990,7 @@ private void saveRecentMessageToHistory(MessageSourceContact msc)
/**
* Updates recent message in history.
*/
- private void updateRecentMessageToHistory(final MessageSourceContact msc)
+ private void updateRecentMessageToHistory(final ComparableEvtObj msg)
{
synchronized(historyID)
{
@@ -972,13 +1020,15 @@ public boolean isMatching()
{
boolean providerFound = false;
boolean contactFound = false;
- for(int i = 0; i < hr.getPropertyNames().length; i++)
+ for(int i = 0;
+ i < hr.getPropertyNames().length;
+ i++)
{
String propName = hr.getPropertyNames()[i];
if(propName.equals(STRUCTURE_NAMES[0]))
{
- if(msc.getProtocolProviderService()
+ if(msg.getProtocolProviderService()
.getAccountID().getAccountUniqueID()
.equals(hr.getPropertyValues()[i]))
{
@@ -987,7 +1037,7 @@ public boolean isMatching()
}
else if(propName.equals(STRUCTURE_NAMES[1]))
{
- if(msc.getContactAddress()
+ if(msg.getContactAddress()
.equals(hr.getPropertyValues()[i]))
{
contactFound = true;
@@ -1016,18 +1066,18 @@ public Map getUpdateChanges()
{
map.put(
propName,
- msc.getProtocolProviderService()
+ msg.getProtocolProviderService()
.getAccountID()
.getAccountUniqueID());
}
else if(propName.equals(STRUCTURE_NAMES[1]))
{
- map.put(propName, msc.getContactAddress());
+ map.put(propName, msg.getContactAddress());
}
else if(propName.equals(STRUCTURE_NAMES[2]))
{
map.put(propName,
- sdf.format(msc.getTimestamp()));
+ sdf.format(msg.getTimestamp()));
}
else if(propName.equals(STRUCTURE_NAMES[3]))
map.put(propName, RECENT_MSGS_VER);
@@ -1175,19 +1225,36 @@ public void contactModified(ContactPropertyChangeEvent evt)
if(contact == null)
return;
- for(MessageSourceContact msc : recentMessages)
+ for(ComparableEvtObj msc : recentMessages)
{
if(contact.equals(msc.getContact()))
{
- msc.setDisplayName(contact.getDisplayName());
-
if(recentQuery != null)
- recentQuery.fireContactChanged(msc);
+ recentQuery.updateContactDisplayName(
+ msc,
+ contact.getDisplayName());
return;
}
}
+ }
+ /**
+ * Indicates that a MetaContact has been modified.
+ * @param evt the MetaContactListEvent containing the corresponding contact
+ */
+ public void metaContactRenamed(MetaContactRenamedEvent evt)
+ {
+ for(ComparableEvtObj msc : recentMessages)
+ {
+ if(evt.getSourceMetaContact().containsContact(msc.getContact()))
+ {
+ if(recentQuery != null)
+ recentQuery.updateContactDisplayName(
+ msc,
+ evt.getNewDisplayName());
+ }
+ }
}
@Override
@@ -1198,14 +1265,12 @@ public void supportedOperationSetsChanged(ContactCapabilitiesEvent event)
if(contact == null)
return;
- for(MessageSourceContact msc : recentMessages)
+ for(ComparableEvtObj msc : recentMessages)
{
if(contact.equals(msc.getContact()))
{
- msc.initDetails(false, contact);
-
if(recentQuery != null)
- recentQuery.fireContactChanged(msc);
+ recentQuery.updateCapabilities(msc, contact);
return;
}
@@ -1219,19 +1284,19 @@ public void supportedOperationSetsChanged(ContactCapabilitiesEvent event)
public void eraseLocallyStoredHistory()
throws IOException
{
+ List toRemove = null;
synchronized(recentMessages)
{
- List toRemove
- = new ArrayList(recentMessages);
+ toRemove = new ArrayList(recentMessages);
recentMessages.clear();
+ }
- if(recentQuery != null)
+ if(recentQuery != null)
+ {
+ for(ComparableEvtObj msc : toRemove)
{
- for(MessageSourceContact msc : toRemove)
- {
- recentQuery.fireContactRemoved(msc);
- }
+ recentQuery.fireContactRemoved(msc);
}
}
}
@@ -1243,10 +1308,10 @@ public void eraseLocallyStoredHistory()
public void eraseLocallyStoredHistory(MetaContact contact)
throws IOException
{
+ List toRemove = null;
synchronized(recentMessages)
{
- List toRemove
- = new ArrayList();
+ toRemove = new ArrayList();
Iterator iter = contact.getContacts();
while(iter.hasNext())
{
@@ -1254,7 +1319,7 @@ public void eraseLocallyStoredHistory(MetaContact contact)
String id = item.getAddress();
ProtocolProviderService provider = item.getProtocolProvider();
- for(MessageSourceContact msc : recentMessages)
+ for(ComparableEvtObj msc : recentMessages)
{
if(msc.getProtocolProviderService().equals(provider)
&& msc.getContactAddress().equals(id))
@@ -1265,16 +1330,14 @@ public void eraseLocallyStoredHistory(MetaContact contact)
}
recentMessages.removeAll(toRemove);
-
- if(recentQuery != null)
+ }
+ if(recentQuery != null)
+ {
+ for(ComparableEvtObj msc : toRemove)
{
- for(MessageSourceContact msc : toRemove)
- {
- recentQuery.fireContactRemoved(msc);
- }
+ recentQuery.fireContactRemoved(msc);
}
}
-
}
/**
@@ -1283,10 +1346,10 @@ public void eraseLocallyStoredHistory(MetaContact contact)
*/
public void eraseLocallyStoredHistory(ChatRoom room)
{
+ ComparableEvtObj toRemove = null;
synchronized(recentMessages)
{
- MessageSourceContact toRemove = null;
- for(MessageSourceContact msg : recentMessages)
+ for(ComparableEvtObj msg : recentMessages)
{
if(msg.getRoom() != null
&& msg.getRoom().equals(room))
@@ -1300,93 +1363,236 @@ public void eraseLocallyStoredHistory(ChatRoom room)
return;
recentMessages.remove(toRemove);
-
- if(recentQuery != null)
- recentQuery.fireContactRemoved(toRemove);
}
+
+ if(recentQuery != null)
+ recentQuery.fireContactRemoved(toRemove);
}
/**
- * The contact query implementation.
+ * Object used to cache recent messages.
*/
- private class MessageHistoryContactQuery
- extends AsyncContactQuery
+ private class ComparableEvtObj
+ implements Comparable
{
- MessageHistoryContactQuery(int contactCount)
+ private EventObject eventObject;
+
+ /**
+ * The protocol provider.
+ */
+ private ProtocolProviderService ppService = null;
+
+ /**
+ * The address.
+ */
+ private String address = null;
+
+ /**
+ * The timestamp.
+ */
+ private Date timestamp = null;
+
+ /**
+ * The contact instance.
+ */
+ private Contact contact = null;
+
+ /**
+ * The room instance.
+ */
+ private ChatRoom room = null;
+
+ /**
+ * Constructs.
+ * @param source used to extract initial values.
+ */
+ ComparableEvtObj(EventObject source)
{
- super(MessageSourceService.this,
- Pattern.compile("",
- Pattern.CASE_INSENSITIVE | Pattern.LITERAL),
- false);
+ update(source);
}
- @Override
- public void run()
+ /**
+ * Extract values from EventObject.
+ * @param source
+ */
+ public void update(EventObject source)
{
- synchronized(recentMessages)
+ this.eventObject = source;
+
+ if(source instanceof MessageDeliveredEvent)
{
- for(MessageSourceContact rm : recentMessages)
- {
- addQueryResult(rm);
- }
+ MessageDeliveredEvent e = (MessageDeliveredEvent)source;
+
+ this.contact = e.getDestinationContact();
+
+ this.address = contact.getAddress();
+ this.ppService = contact.getProtocolProvider();
+ this.timestamp = e.getTimestamp();
+ }
+ else if(source instanceof MessageReceivedEvent)
+ {
+ MessageReceivedEvent e = (MessageReceivedEvent)source;
+
+ this.contact = e.getSourceContact();
+
+ this.address = contact.getAddress();
+ this.ppService = contact.getProtocolProvider();
+ this.timestamp = e.getTimestamp();
}
+ else if(source instanceof ChatRoomMessageDeliveredEvent)
+ {
+ ChatRoomMessageDeliveredEvent e
+ = (ChatRoomMessageDeliveredEvent)source;
+
+ this.room = e.getSourceChatRoom();
+
+ this.address = room.getIdentifier();
+ this.ppService = room.getParentProvider();
+ this.timestamp = e.getTimestamp();
+ }
+ else if(source instanceof ChatRoomMessageReceivedEvent)
+ {
+ ChatRoomMessageReceivedEvent e
+ = (ChatRoomMessageReceivedEvent)source;
+
+ this.room = e.getSourceChatRoom();
+
+ this.address = room.getIdentifier();
+ this.ppService = room.getParentProvider();
+ this.timestamp = e.getTimestamp();
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ComparableEvtObj{" +
+ "address='" + address + '\'' +
+ ", ppService=" + ppService +
+ '}';
+ }
+
+ /**
+ * The timestamp of the message.
+ * @return the timestamp of the message.
+ */
+ public Date getTimestamp()
+ {
+ return timestamp;
+ }
+
+ /**
+ * The contact.
+ * @return the contact.
+ */
+ public Contact getContact()
+ {
+ return contact;
+ }
+
+ /**
+ * The room.
+ * @return the room.
+ */
+ public ChatRoom getRoom()
+ {
+ return room;
+ }
+
+ /**
+ * The protocol provider.
+ * @return the protocol provider.
+ */
+ public ProtocolProviderService getProtocolProviderService()
+ {
+ return ppService;
}
/**
- * Notifies the ContactQueryListeners registered with this
- * ContactQuery that a new SourceContact has been
- * received.
- *
- * @param contact the SourceContact which has been received and
- * which the registered ContactQueryListeners are to be notified
- * about
+ * The address.
+ * @return the address.
*/
- public void fireContactReceived(SourceContact contact)
+ public String getContactAddress()
{
- fireContactReceived(contact, false);
+ if(this.address != null)
+ return this.address;
+
+ return null;
}
/**
- * Notifies the ContactQueryListeners registered with this
- * ContactQuery that a SourceContact has been
- * changed.
- *
- * @param contact the SourceContact which has been changed and
- * which the registered ContactQueryListeners are to be notified
- * about
+ * The event object.
+ * @return the event object.
*/
- public void fireContactChanged(SourceContact contact)
+ public EventObject getEventObject()
{
- super.fireContactChanged(contact);
+ return eventObject;
}
/**
- * Notifies the ContactQueryListeners registered with this
- * ContactQuery that a SourceContact has been
- * removed.
- *
- * @param contact the SourceContact which has been removed and
- * which the registered ContactQueryListeners are to be notified
- * about
+ * Compares two ComparableEvtObj.
+ * @param o the object to compare with
+ * @return 0, less than zero, greater than zero, if equals,
+ * less or greater.
*/
- public void fireContactRemoved(SourceContact contact)
+ @Override
+ public int compareTo(ComparableEvtObj o)
{
- super.fireContactRemoved(contact);
+ if(o == null
+ || o.getTimestamp() == null)
+ return 1;
+
+ return o.getTimestamp()
+ .compareTo(getTimestamp());
}
/**
- * Adds a specific SourceContact to the list of
- * SourceContacts to be returned by this ContactQuery in
- * response to {@link #getQueryResults()}.
- *
- * @param sourceContact the SourceContact to be added to the
- * queryResults of this ContactQuery
- * @return true if the queryResults of this
- * ContactQuery has changed in response to the call
+ * Checks if equals, and if this event object is used to create
+ * a MessageSourceContact, if the supplied Object is instance
+ * of MessageSourceContact.
+ * @param o the object to check.
+ * @return true if equals.
*/
- public boolean addQueryResult(SourceContact sourceContact)
+ @Override
+ public boolean equals(Object o)
+ {
+ if(this == o)
+ return true;
+ if(o == null
+ || (!(o instanceof MessageSourceContact)
+ && getClass() != o.getClass()))
+ return false;
+
+ if(o instanceof ComparableEvtObj)
+ {
+ ComparableEvtObj that = (ComparableEvtObj) o;
+
+ if(!address.equals(that.address))
+ return false;
+ if(!ppService.equals(that.ppService))
+ return false;
+ }
+ else if(o instanceof MessageSourceContact)
+ {
+ MessageSourceContact that = (MessageSourceContact)o;
+
+ if(!address.equals(that.getContactAddress()))
+ return false;
+ if(!ppService.equals(that.getProtocolProviderService()))
+ return false;
+ }
+ else
+ return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
{
- return super.addQueryResult(sourceContact);
+ int result = address.hashCode();
+ result = 31 * result + ppService.hashCode();
+ return result;
}
}
}
diff --git a/src/net/java/sip/communicator/impl/msghistory/msghistory.manifest.mf b/src/net/java/sip/communicator/impl/msghistory/msghistory.manifest.mf
index 9748e9272..93a89c932 100644
--- a/src/net/java/sip/communicator/impl/msghistory/msghistory.manifest.mf
+++ b/src/net/java/sip/communicator/impl/msghistory/msghistory.manifest.mf
@@ -12,6 +12,7 @@ Import-Package: org.osgi.framework,
net.java.sip.communicator.service.history.event,
net.java.sip.communicator.service.msghistory,
net.java.sip.communicator.service.contactlist,
+ net.java.sip.communicator.service.contactlist.event,
net.java.sip.communicator.service.contactsource,
net.java.sip.communicator.service.history.records,
net.java.sip.communicator.service.muc,
diff --git a/src/net/java/sip/communicator/impl/muc/MUCCustomContactActionService.java b/src/net/java/sip/communicator/impl/muc/MUCCustomContactActionService.java
index 1dac54447..97a2ca15a 100644
--- a/src/net/java/sip/communicator/impl/muc/MUCCustomContactActionService.java
+++ b/src/net/java/sip/communicator/impl/muc/MUCCustomContactActionService.java
@@ -8,8 +8,6 @@
import java.util.*;
-import org.jitsi.service.resources.*;
-
import net.java.sip.communicator.plugin.desktoputil.chat.*;
import net.java.sip.communicator.service.contactsource.*;
import net.java.sip.communicator.service.customcontactactions.*;
@@ -17,6 +15,8 @@
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
+import org.jitsi.service.resources.*;
+
/**
* Implements CustomContactActionsService for MUC contact source.
*
@@ -643,7 +643,7 @@ public String getText(SourceContact actionSource)
((ChatRoomSourceContact)actionSource).getProvider(),
((ChatRoomSourceContact)actionSource).getChatRoomID());
if(openAutomaticallyValue == null)
- openAutomaticallyValue = MUCService.OPEN_ON_IMPORTANT_MESSAGE;
+ openAutomaticallyValue = MUCService.DEFAULT_AUTO_OPEN_BEHAVIOUR;
String openAutomaticallyKey = MUCService.autoOpenConfigValuesTexts
.get(openAutomaticallyValue);
return "" + text + "...
("
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/AbstractCallJabberGTalkImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/AbstractCallJabberGTalkImpl.java
index 8155cf455..cd314cee6 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/AbstractCallJabberGTalkImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/AbstractCallJabberGTalkImpl.java
@@ -85,9 +85,12 @@ public abstract void modifyVideoContent()
*/
public T getPeer(String sid)
{
+ if (sid == null)
+ return null;
+
for(T peer : getCallPeerList())
{
- if (peer.getSID() != null && peer.getSID().equals(sid))
+ if (sid.equals(peer.getSID()))
return peer;
}
return null;
@@ -118,9 +121,12 @@ public boolean containsSID(String sid)
*/
public T getPeerBySessInitPacketID(String id)
{
+ if (id == null)
+ return null;
+
for(T peer : getCallPeerList())
{
- if (peer.getSessInitID().equals(id))
+ if (id.equals(peer.getSessInitID()))
return peer;
}
return null;
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java
index eb6449cf2..8577d4bac 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java
@@ -19,6 +19,7 @@
*
* @author Lyubomir Marinov
* @author Boris Grozev
+ * @author George Politis
*/
public class ColibriConferenceIQ
extends IQ
@@ -49,17 +50,22 @@ public class ColibriConferenceIQ
*/
public static final int[] NO_SSRCS = new int[0];
+ /**
+ * The list of {@link ChannelBundle}s included into this conference
+ * IQ.
+ */
+ private final List channelBundles
+ = new LinkedList();
+
/**
* The list of {@link Content}s included into this conference IQ.
*/
private final List contents = new LinkedList();
/**
- * The list of {@link ChannelBundle}s included into this conference
- * IQ.
+ * The list of Endpoints included into this conference IQ.
*/
- private final List channelBundles
- = new LinkedList();
+ private final List endpoints = new LinkedList();
/**
* The ID of the conference represented by this IQ.
@@ -69,14 +75,9 @@ public class ColibriConferenceIQ
/**
* Media recording.
*/
- public Recording recording = null;
-
- private RTCPTerminationStrategy rtcpTerminationStrategy = null;
+ private Recording recording;
- /**
- * The list of Endpoints included into this conference IQ.
- */
- private final List endpoints = new LinkedList();
+ private RTCPTerminationStrategy rtcpTerminationStrategy;
/** Initializes a new ColibriConferenceIQ instance. */
public ColibriConferenceIQ()
@@ -84,19 +85,19 @@ public ColibriConferenceIQ()
}
/**
- * Initializes a new {@link Content} instance with a specific name and adds
- * it to the list of Content instances included into this
- * conference IQ.
- *
- * @param contentName the name which which the new Content instance
- * is to be initialized
- * @return true if the list of Content instances included
- * into this conference IQ has been modified as a result of the
- * method call; otherwise, false
+ * Adds a specific {@link Content} instance to the list of Content
+ * instances included into this conference IQ.
+ * @param channelBundle the ChannelBundle to add.
*/
- public boolean addContent(String contentName)
+ public boolean addChannelBundle(ChannelBundle channelBundle)
{
- return addContent(new Content(contentName));
+ if (channelBundle == null)
+ throw new NullPointerException("channelBundle");
+
+ return
+ channelBundles.contains(channelBundles)
+ ? false
+ : channelBundles.add(channelBundle);
}
/**
@@ -120,19 +121,40 @@ public boolean addContent(Content content)
}
/**
- * Adds a specific {@link Content} instance to the list of Content
- * instances included into this conference IQ.
- * @param the ChannelBundle to add.
+ * Initializes a new {@link Content} instance with a specific name and adds
+ * it to the list of Content instances included into this
+ * conference IQ.
+ *
+ * @param contentName the name which which the new Content instance
+ * is to be initialized
+ * @return true if the list of Content instances included
+ * into this conference IQ has been modified as a result of the
+ * method call; otherwise, false
*/
- public boolean addChannelBundle(ChannelBundle channelBundle)
+ public boolean addContent(String contentName)
{
- if (channelBundle == null)
- throw new NullPointerException("channelBundle");
+ return addContent(new Content(contentName));
+ }
- return channelBundles.contains(channelBundles)
- ? false
- : channelBundles.add(channelBundle);
+ /**
+ * Add an Endpoint to this ColibriConferenceIQ.
+ * @param endpoint the Endpoint to add.
+ */
+ public void addEndpoint(Endpoint endpoint)
+ {
+ endpoints.add(endpoint);
+ }
+ /**
+ * Returns a list of the ChannelBundles included into this
+ * conference IQ.
+ *
+ * @return an unmodifiable List of the ChannelBundles
+ * included into this conference IQ.
+ */
+ public List getChannelBundles()
+ {
+ return Collections.unmodifiableList(channelBundles);
}
/**
@@ -157,10 +179,11 @@ public String getChildElementXML()
List contents = getContents();
List channelBundles = getChannelBundles();
- boolean hasChildren = recording != null
- || rtcpTerminationStrategy != null
- || contents.size() > 0
- || channelBundles.size() > 0;
+ boolean hasChildren
+ = (recording != null)
+ || (rtcpTerminationStrategy != null)
+ || (contents.size() > 0)
+ || (channelBundles.size() > 0);
if (!hasChildren)
{
@@ -175,7 +198,6 @@ public String getChildElementXML()
channelBundle.toXML(xml);
if (recording != null)
recording.toXML(xml);
-
if (rtcpTerminationStrategy != null)
rtcpTerminationStrategy.toXML(xml);
@@ -197,8 +219,10 @@ public String getChildElementXML()
public Content getContent(String contentName)
{
for (Content content : getContents())
+ {
if (contentName.equals(content.getName()))
return content;
+ }
return null;
}
@@ -215,15 +239,14 @@ public List getContents()
}
/**
- * Returns a list of the ChannelBundles included into this
- * conference IQ.
- *
- * @return an unmodifiable List of the ChannelBundles
- * included into this conference IQ.
+ * Returns the list of Endpoints included in this
+ * ColibriConferenceIQ.
+ * @return the list of Endpoints included in this
+ * ColibriConferenceIQ.
*/
- public List getChannelBundles()
+ public List getEndpoints()
{
- return Collections.unmodifiableList(channelBundles);
+ return Collections.unmodifiableList(endpoints);
}
/**
@@ -236,24 +259,6 @@ public String getID()
return id;
}
- /**
- * Gets the value of the recording field.
- * @return the value of the recording field.
- */
- public Recording getRecording()
- {
- return recording;
- }
-
- /**
- * Sets the recording field.
- * @param recording the value to set.
- */
- public void setRecording(Recording recording)
- {
- this.recording = recording;
- }
-
/**
* Returns a Content from the list of Contents of this
* conference IQ which has a specific name. If no such
@@ -274,10 +279,23 @@ public Content getOrCreateContent(String contentName)
content = new Content(contentName);
addContent(content);
}
-
return content;
}
+ /**
+ * Gets the value of the recording field.
+ * @return the value of the recording field.
+ */
+ public Recording getRecording()
+ {
+ return recording;
+ }
+
+ public RTCPTerminationStrategy getRTCPTerminationStrategy()
+ {
+ return rtcpTerminationStrategy;
+ }
+
/**
* Removes a specific {@link Content} instance from the list of
* Content instances included into this conference IQ.
@@ -303,1044 +321,1141 @@ public void setID(String id)
this.id = id;
}
- public RTCPTerminationStrategy getRTCPTerminationStrategy()
+ /**
+ * Sets the recording field.
+ * @param recording the value to set.
+ */
+ public void setRecording(Recording recording)
{
- return rtcpTerminationStrategy;
+ this.recording = recording;
}
- public void setRTCPTerminationStrategy(RTCPTerminationStrategy rtcpTerminationStrategy)
+ public void setRTCPTerminationStrategy(
+ RTCPTerminationStrategy rtcpTerminationStrategy)
{
this.rtcpTerminationStrategy = rtcpTerminationStrategy;
}
/**
- * Returns the list of Endpoints included in this
- * ColibriConferenceIQ.
- * @return the list of Endpoints included in this
- * ColibriConferenceIQ.
+ * Represents a channel included into a content of a Jitsi
+ * Videobridge conference IQ.
*/
- public List getEndpoints()
+ public static class Channel
+ extends ChannelCommon
{
- return Collections.unmodifiableList(endpoints);
- }
+ /**
+ * The name of the XML attribute of a channel which represents
+ * its direction.
+ */
+ public static final String DIRECTION_ATTR_NAME = "direction";
- /**
- * Add an Endpoint to this ColibriConferenceIQ.
- * @param endpoint the Endpoint to add.
- */
- public void addEndpoint(Endpoint endpoint)
- {
- endpoints.add(endpoint);
- }
- /**
- * Class contains common code for both Channel and
- * SctpConnection IQ classes.
- *
- * @author Pawel Domas
- */
- public static abstract class ChannelCommon
- {
/**
- * The XML name of the endpoint attribute which specifies the
- * optional identifier of the endpoint of the conference participant
- * associated with a channel. The value of the
- * endpoint attribute is an opaque String from the
- * point of view of Jitsi Videobridge.
+ * The XML element name of a channel of a content of a
+ * Jitsi Videobridge conference IQ.
*/
- public static final String ENDPOINT_ATTR_NAME = "endpoint";
+ public static final String ELEMENT_NAME = "channel";
/**
- * The XML name of the expire attribute of a channel
- * of a content of a conference IQ which represents
- * the value of the expire property of
+ * The XML name of the host attribute of a channel of
+ * a content of a conference IQ which represents the
+ * value of the host property of
* ColibriConferenceIQ.Channel.
+ *
+ * @deprecated The attribute is supported for the purposes of
+ * compatibility with legacy versions of Jitsi and Jitsi Videobridge.
*/
- public static final String EXPIRE_ATTR_NAME = "expire";
+ @Deprecated
+ public static final String HOST_ATTR_NAME = "host";
/**
- * The name of the "channel-bundle-id" attribute.
+ * The XML name of the last-n attribute of a video
+ * channel which specifies the maximum number of video RTP
+ * streams to be sent from Jitsi Videobridge to the endpoint associated
+ * with the video channel. The value of the last-n
+ * attribute is a positive number.
*/
- public static final String CHANNEL_BUNDLE_ID_ATTR_NAME
- = "channel-bundle-id";
+ public static final String LAST_N_ATTR_NAME = "last-n";
/**
- * The value of the expire property of
- * ColibriConferenceIQ.Channel which indicates that no actual
- * value has been specified for the property in question.
+ * The XML name of the receive-simulcast-layer attribute of a
+ * video Channel which specifies the target quality of the
+ * simulcast substreams to be sent from Jitsi Videobridge to the
+ * endpoint associated with the video Channel. The value of the
+ * receive-simulcast-layer attribute is an unsigned integer.
+ * Typically used for debugging purposes.
*/
- public static final int EXPIRE_NOT_SPECIFIED = -1;
+ public static final String RECEIVING_SIMULCAST_LAYER
+ = "receive-simulcast-layer";
/**
- * The XML name of the initiator attribute of a
- * channel of a content of a conference IQ
- * which represents the value of the initiator property of
+ * The XML name of the rtcpport attribute of a channel
+ * of a content of a conference IQ which represents
+ * the value of the rtcpPort property of
* ColibriConferenceIQ.Channel.
+ *
+ * @deprecated The attribute is supported for the purposes of
+ * compatibility with legacy versions of Jitsi and Jitsi Videobridge.
*/
- public static final String INITIATOR_ATTR_NAME = "initiator";
+ @Deprecated
+ public static final String RTCP_PORT_ATTR_NAME = "rtcpport";
+
+ public static final String RTP_LEVEL_RELAY_TYPE_ATTR_NAME
+ = "rtp-level-relay-type";
/**
- * The identifier of the endpoint of the conference participant
- * associated with this Channel.
+ * The XML name of the rtpport attribute of a channel
+ * of a content of a conference IQ which represents
+ * the value of the rtpPort property of
+ * ColibriConferenceIQ.Channel.
+ *
+ * @deprecated The attribute is supported for the purposes of
+ * compatibility with legacy versions of Jitsi and Jitsi Videobridge.
*/
- private String endpoint;
+ @Deprecated
+ public static final String RTP_PORT_ATTR_NAME = "rtpport";
/**
- * The number of seconds of inactivity after which the channel
- * represented by this instance expires.
+ * The name of the XML element which is a child of the <channel>
+ * element and which identifies/specifies an (RTP) SSRC which has been
+ * seen/received on the respective Channel.
*/
- private int expire = EXPIRE_NOT_SPECIFIED;
+ public static final String SSRC_ELEMENT_NAME = "ssrc";
/**
- * The indicator which determines whether the conference focus is the
- * initiator/offerer (as opposed to the responder/answerer) of the media
- * negotiation associated with this instance.
+ * The direction of the channel represented by this instance.
*/
- private Boolean initiator;
-
- private IceUdpTransportPacketExtension transport;
+ private MediaDirection direction;
/**
- * XML element name.
+ * The host of the channel represented by this instance.
+ *
+ * @deprecated The field is supported for the purposes of compatibility
+ * with legacy versions of Jitsi and Jitsi Videobridge.
*/
- private String elementName;
+ @Deprecated
+ private String host;
/**
- * The channel-bundle-id attribute of this CommonChannel.
+ * The maximum number of video RTP streams to be sent from Jitsi
+ * Videobridge to the endpoint associated with this video
+ * Channel.
*/
- private String channelBundleId = null;
+ private Integer lastN;
/**
- * Initializes this class with given XML elementName.
- * @param elementName XML element name to be used for producing XML
- * representation of derived IQ class.
+ * The payload-type elements defined by XEP-0167: Jingle RTP
+ * Sessions associated with this channel.
*/
- protected ChannelCommon(String elementName)
- {
- this.elementName = elementName;
- }
+ private final List payloadTypes
+ = new ArrayList();
/**
- * Gets the identifier of the endpoint of the conference participant
- * associated with this Channel.
+ * The target quality of the simulcast substreams to be sent from Jitsi
+ * Videobridge to the endpoint associated with this video
+ * Channel.
+ */
+ private Integer receivingSimulcastLayer;
+
+ /**
+ * The RTCP port of the channel represented by this instance.
*
- * @return the identifier of the endpoint of the conference participant
- * associated with this Channel
+ * @deprecated The field is supported for the purposes of compatibility
+ * with legacy versions of Jitsi and Jitsi Videobridge.
*/
- public String getEndpoint()
- {
- return endpoint;
- }
+ @Deprecated
+ private int rtcpPort;
/**
- * Gets the number of seconds of inactivity after which the
- * channel represented by this instance expires.
+ * The type of RTP-level relay (in the terms specified by RFC 3550
+ * "RTP: A Transport Protocol for Real-Time Applications" in
+ * section 2.3 "Mixers and Translators") used for this
+ * Channel.
+ */
+ private RTPLevelRelayType rtpLevelRelayType;
+
+ /**
+ * The RTP port of the channel represented by this instance.
*
- * @return the number of seconds of inactivity after which the
- * channel represented by this instance expires
+ * @deprecated The field is supported for the purposes of compatibility
+ * with legacy versions of Jitsi and Jitsi Videobridge.
*/
- public int getExpire()
- {
- return expire;
- }
+ @Deprecated
+ private int rtpPort;
- public IceUdpTransportPacketExtension getTransport()
+ /**
+ * The SourceGroupPacketExtensions of this channel.
+ */
+ private List sourceGroups;
+
+ /**
+ * The SourcePacketExtensions of this channel.
+ */
+ private final List sources
+ = new LinkedList();
+
+ /**
+ * The list of (RTP) SSRCs which have been seen/received on this
+ * Channel by now. These may exclude SSRCs which are no longer
+ * active. Set by the Jitsi Videobridge server, not its clients.
+ */
+ private int[] ssrcs = NO_SSRCS;
+
+ /** Initializes a new Channel instance. */
+ public Channel()
{
- return transport;
+ super(Channel.ELEMENT_NAME);
}
/**
- * Gets the indicator which determines whether the conference focus is
- * the initiator/offerer (as opposed to the responder/answerer) of the
- * media negotiation associated with this instance.
+ * Adds a payload-type element defined by XEP-0167: Jingle RTP
+ * Sessions to this channel.
*
- * @return {@link Boolean#TRUE} if the conference focus is the
- * initiator/offerer of the media negotiation associated with this
- * instance, {@link Boolean#FALSE} if the conference focus is the
- * responder/answerer or null if the initiator state
- * is unspecified
+ * @param payloadType the payload-type element to be added to
+ * this channel
+ * @return true if the list of payload-type elements
+ * associated with this channel has been modified as part of
+ * the method call; otherwise, false
+ * @throws NullPointerException if the specified payloadType is
+ * null
*/
- public Boolean isInitiator()
+ public boolean addPayloadType(PayloadTypePacketExtension payloadType)
{
- return initiator;
+ if (payloadType == null)
+ throw new NullPointerException("payloadType");
+
+ // Make sure that the COLIBRI namespace is used.
+ payloadType.setNamespace(null);
+ for (ParameterPacketExtension p : payloadType.getParameters())
+ p.setNamespace(null);
+
+ return
+ payloadTypes.contains(payloadType)
+ ? false
+ : payloadTypes.add(payloadType);
}
/**
- * Get the channel-bundle-id attribute of this CommonChannel.
- * @return the channel-bundle-id attribute of this
- * CommonChannel.
+ * Adds a SourcePacketExtension to the list of sources of this
+ * channel.
+ *
+ * @param source the SourcePacketExtension to add to the list
+ * of sources of this channel
+ * @return true if the list of sources of this channel changed
+ * as a result of the execution of the method; otherwise, false
*/
- public String getChannelBundleId()
+ public synchronized boolean addSource(SourcePacketExtension source)
{
- return channelBundleId;
+ if (source == null)
+ throw new NullPointerException("source");
+
+ return sources.contains(source) ? false : sources.add(source);
}
/**
- * Sets the identifier of the endpoint of the conference participant
- * associated with this Channel.
+ * Adds a SourceGroupPacketExtension to the list of source
+ * groups of this channel.
*
- * @param endpoint the identifier of the endpoint of the conference
- * participant associated with this Channel
+ * @param sourceGroup the SourcePacketExtension to add to the
+ * list of sources of this channel
+ *
+ * @return true if the list of sources of this channel changed
+ * as a result of the execution of the method; otherwise, false
*/
- public void setEndpoint(String endpoint)
+ public synchronized boolean addSourceGroup(
+ SourceGroupPacketExtension sourceGroup)
{
- this.endpoint = endpoint;
+ if (sourceGroup == null)
+ throw new NullPointerException("sourceGroup");
+
+ if (sourceGroups == null)
+ sourceGroups = new LinkedList();
+
+ return
+ sourceGroups.contains(sourceGroup)
+ ? false
+ : sourceGroups.add(sourceGroup);
}
/**
- * Sets the number of seconds of inactivity after which the
- * channel represented by this instance expires.
+ * Adds a specific (RTP) SSRC to the list of SSRCs seen/received on this
+ * Channel. Invoked by the Jitsi Videobridge server, not its
+ * clients.
*
- * @param expire the number of seconds of activity after which the
- * channel represented by this instance expires
- * @throws IllegalArgumentException if the value of the specified
- * expire is other than {@link #EXPIRE_NOT_SPECIFIED} and
- * negative
+ * @param ssrc the (RTP) SSRC to be added to the list of SSRCs
+ * seen/received on this Channel
+ * @return true if the list of SSRCs seen/received on this
+ * Channel has been modified as part of the method call;
+ * otherwise, false
*/
- public void setExpire(int expire)
+ public synchronized boolean addSSRC(int ssrc)
{
- if ((expire != EXPIRE_NOT_SPECIFIED) && (expire < 0))
- throw new IllegalArgumentException("expire");
+ // contains
+ for (int i = 0; i < ssrcs.length; i++)
+ {
+ if (ssrcs[i] == ssrc)
+ return false;
+ }
- this.expire = expire;
+ // add
+ int[] newSSRCs = new int[ssrcs.length + 1];
+
+ System.arraycopy(ssrcs, 0, newSSRCs, 0, ssrcs.length);
+ newSSRCs[ssrcs.length] = ssrc;
+ ssrcs = newSSRCs;
+ return true;
}
/**
- * Sets the indicator which determines whether the conference focus is
- * the initiator/offerer (as opposed to the responder/answerer) of the
- * media negotiation associated with this instance.
+ * Gets the direction of this Channel.
*
- * @param initiator {@link Boolean#TRUE} if the conference focus is the
- * initiator/offerer of the media negotiation associated with this
- * instance, {@link Boolean#FALSE} if the conference focus is the
- * responder/answerer or null if the initiator state
- * is to be unspecified
+ * @return the direction of this Channel.
*/
- public void setInitiator(Boolean initiator)
+ public MediaDirection getDirection()
{
- this.initiator = initiator;
+ return (direction == null) ? MediaDirection.SENDRECV : direction;
}
- public void setTransport(IceUdpTransportPacketExtension transport)
+ /**
+ * Gets the IP address (as a String value) of the host on which
+ * the channel represented by this instance has been allocated.
+ *
+ * @return a String value which represents the IP address of
+ * the host on which the channel represented by this instance
+ * has been allocated
+ *
+ * @deprecated The method is supported for the purposes of compatibility
+ * with legacy versions of Jitsi and Jitsi Videobridge.
+ */
+ @Deprecated
+ public String getHost()
{
- this.transport = transport;
+ return host;
}
/**
- * Sets the channel-bundle-id attribute of this CommonChannel.
- * @param channelBundleId the value to set.
+ * Gets the maximum number of video RTP streams to be sent from Jitsi
+ * Videobridge to the endpoint associated with this video
+ * Channel.
+ *
+ * @return the maximum number of video RTP streams to be sent from Jitsi
+ * Videobridge to the endpoint associated with this video
+ * Channel
*/
- public void setChannelBundleId(String channelBundleId)
+ public Integer getLastN()
{
- this.channelBundleId = channelBundleId;
+ return lastN;
}
/**
- * Derived class implements this method in order to print additional
- * attributes to main XML element.
- * @param xml StringBuilder to which the XML
- * String representation of this Channel
- * is to be appended
+ * Gets a list of payload-type elements defined by XEP-0167:
+ * Jingle RTP Sessions added to this channel.
+ *
+ * @return an unmodifiable List of payload-type
+ * elements defined by XEP-0167: Jingle RTP Sessions added to this
+ * channel
*/
- protected abstract void printAttributes(StringBuilder xml);
+ public List getPayloadTypes()
+ {
+ return Collections.unmodifiableList(payloadTypes);
+ }
/**
- * Indicates whether there are some contents that should be printed as
- * child elements of this IQ. If true is returned
- * {@link #printContent(StringBuilder)} method will be called when
- * XML representation of this IQ is being constructed.
- * @return true if there are content to be printed as child
- * elements of this IQ or false otherwise.
+ * Gets the target quality of the simulcast substreams to be sent from
+ * Jitsi Videobridge to the endpoint associated with this video
+ * Channel.
+ *
+ * @return the target quality of the simulcast substreams to be sent
+ * from Jitsi Videobridge to the endpoint associated with this video
+ * Channel.
*/
- protected abstract boolean hasContent();
+ public Integer getReceivingSimulcastLayer()
+ {
+ return receivingSimulcastLayer;
+ }
/**
- * Implement in order to print content child elements of this IQ using
- * given StringBuilder. Called during construction of XML
- * representation if {@link #hasContent()} returns true.
+ * Gets the port which has been allocated to this channel for
+ * the purposes of transmitting RTCP packets.
*
- * @param xml the StringBuilder to which the XML
- * String representation of this Channel
- * is to be appended.
+ * @return the port which has been allocated to this channel
+ * for the purposes of transmitting RTCP packets
+ *
+ * @deprecated The method is supported for the purposes of compatibility
+ * with legacy versions of Jitsi and Jitsi Videobridge.
*/
- protected abstract void printContent(StringBuilder xml);
+ @Deprecated
+ public int getRTCPPort()
+ {
+ return rtcpPort;
+ }
/**
- * Appends the XML String representation of this
- * Channel to a specific StringBuilder.
- *
- * @param xml the StringBuilder to which the XML
- * String representation of this Channel is to be
- * appended
+ * Gets the type of RTP-level relay (in the terms specified by RFC 3550
+ * "RTP: A Transport Protocol for Real-Time Applications" in
+ * section 2.3 "Mixers and Translators") used for this
+ * Channel.
+ *
+ * @return the type of RTP-level relay used for this Channel
*/
- public void toXML(StringBuilder xml)
+ public RTPLevelRelayType getRTPLevelRelayType()
{
- xml.append('<').append(elementName);
+ return rtpLevelRelayType;
+ }
- // endpoint
- String endpoint = getEndpoint();
+ /**
+ * Gets the port which has been allocated to this channel for
+ * the purposes of transmitting RTP packets.
+ *
+ * @return the port which has been allocated to this channel
+ * for the purposes of transmitting RTP packets
+ *
+ * @deprecated The method is supported for the purposes of compatibility
+ * with legacy versions of Jitsi and Jitsi Videobridge.
+ */
+ @Deprecated
+ public int getRTPPort()
+ {
+ return rtpPort;
+ }
- if (endpoint != null)
- {
- xml.append(' ').append(ENDPOINT_ATTR_NAME).append("='")
- .append(endpoint).append('\'');
- }
+ /**
+ * Gets the list of SourceGroupPacketExtensionss which
+ * represent the source groups of this channel.
+ *
+ * @return a List of SourceGroupPacketExtensions which
+ * represent the source groups of this channel
+ */
+ public synchronized List getSourceGroups()
+ {
+ return
+ (sourceGroups == null)
+ ? null
+ : new ArrayList(sourceGroups);
+ }
- // expire
- int expire = getExpire();
+ /**
+ * Gets the list of SourcePacketExtensionss which represent the
+ * sources of this channel.
+ *
+ * @return a List of SourcePacketExtensions which
+ * represent the sources of this channel
+ */
+ public synchronized List getSources()
+ {
+ return new ArrayList(sources);
+ }
- if (expire >= 0)
- {
- xml.append(' ').append(EXPIRE_ATTR_NAME).append("='")
- .append(expire).append('\'');
- }
+ /**
+ * Gets (a copy of) the list of (RTP) SSRCs seen/received on this
+ * Channel.
+ *
+ * @return an array of ints which represents (a copy of) the
+ * list of (RTP) SSRCs seen/received on this Channel
+ */
+ public synchronized int[] getSSRCs()
+ {
+ return (ssrcs.length == 0) ? NO_SSRCS : ssrcs.clone();
+ }
- // initiator
- Boolean initiator = isInitiator();
+ @Override
+ protected boolean hasContent()
+ {
+ List payloadTypes = getPayloadTypes();
- if (initiator != null)
+ if (!payloadTypes.isEmpty())
+ return true;
+
+ List sources = getSources();
+ if (!sources.isEmpty())
+ return true;
+
+ int[] ssrcs = getSSRCs();
+
+ return (ssrcs.length != 0);
+ }
+
+ @Override
+ protected void printAttributes(StringBuilder xml)
+ {
+ // direction
+ MediaDirection direction = getDirection();
+
+ if ((direction != null) && (direction != MediaDirection.SENDRECV))
{
- xml.append(' ').append(INITIATOR_ATTR_NAME).append("='")
- .append(initiator).append('\'');
+ xml.append(' ').append(DIRECTION_ATTR_NAME).append("='")
+ .append(direction.toString()).append('\'');
}
- String channelBundleId = getChannelBundleId();
- if (channelBundleId != null)
+ // host
+ String host = getHost();
+
+ if (host != null)
{
- xml.append(' ').append(CHANNEL_BUNDLE_ID_ATTR_NAME)
- .append("='").append(channelBundleId).append('\'');
+ xml.append(' ').append(HOST_ATTR_NAME).append("='").append(host)
+ .append('\'');
}
- // Print derived class attributes
- printAttributes(xml);
+ // lastN
+ Integer lastN = getLastN();
- IceUdpTransportPacketExtension transport = getTransport();
- boolean hasTransport = (transport != null);
- if (hasTransport || hasContent())
+ if (lastN != null)
{
- xml.append('>');
- if(hasContent())
- printContent(xml);
- if (hasTransport)
- xml.append(transport.toXML());
- xml.append("").append(elementName).append('>');
+ xml.append(' ').append(LAST_N_ATTR_NAME).append("='")
+ .append(lastN).append('\'');
}
- else
+
+ // rtcpPort
+ int rtcpPort = getRTCPPort();
+
+ if (rtcpPort > 0)
{
- xml.append(" />");
+ xml.append(' ').append(RTCP_PORT_ATTR_NAME).append("='")
+ .append(rtcpPort).append('\'');
}
- }
- }
-
- public static class RTCPTerminationStrategy
- {
- public static final String ELEMENT_NAME = "rtcp-termination-strategy";
- public static final String NAME_ATTR_NAME = "name";
+ // rtpLevelRelayType
+ RTPLevelRelayType rtpLevelRelayType = getRTPLevelRelayType();
- private String name;
+ if (rtpLevelRelayType != null)
+ {
+ xml.append(' ').append(RTP_LEVEL_RELAY_TYPE_ATTR_NAME)
+ .append("='").append(rtpLevelRelayType).append('\'');
+ }
- public void setName(String name)
- {
- this.name = name;
- }
+ // rtpPort
+ int rtpPort = getRTPPort();
- public String getName()
- {
- return name;
+ if (rtpPort > 0)
+ {
+ xml.append(' ').append(RTP_PORT_ATTR_NAME).append("='")
+ .append(rtpPort).append('\'');
+ }
}
- public void toXML(StringBuilder xml)
+ @Override
+ protected void printContent(StringBuilder xml)
{
- xml.append('<').append(ELEMENT_NAME);
- xml.append(' ').append(NAME_ATTR_NAME).append("='")
- .append(name).append('\'');
- xml.append("/>");
- }
- }
+ List payloadTypes = getPayloadTypes();
+ List sources = getSources();
+ List souceGroups = getSourceGroups();
+ int[] ssrcs = getSSRCs();
- /**
- * Represents a "channel-bundle" element.
- */
- public static class ChannelBundle
- {
- /**
- * The name of the "channel-bundle" element.
- */
- public static final String ELEMENT_NAME = "channel-bundle";
+ for (PayloadTypePacketExtension payloadType : payloadTypes)
+ xml.append(payloadType.toXML());
- /**
- * The name of the "id" attribute.
- */
- public static final String ID_ATTR_NAME = "id";
+ for (SourcePacketExtension source : sources)
+ xml.append(source.toXML());
- /**
- * The ID of this ChannelBundle.
- */
- private String id;
+ if (souceGroups != null && souceGroups.size() != 0)
+ for (SourceGroupPacketExtension sourceGroup : souceGroups)
+ xml.append(sourceGroup.toXML());
- /**
- * The transport element of this ChannelBundle.
- */
- private IceUdpTransportPacketExtension transport;
+ for (int i = 0; i < ssrcs.length; i++)
+ {
+ xml.append('<').append(SSRC_ELEMENT_NAME).append('>')
+ .append(Long.toString(ssrcs[i] & 0xFFFFFFFFL))
+ .append("").append(SSRC_ELEMENT_NAME)
+ .append('>');
+ }
+ }
/**
- * Initializes a new ChannelBundle with the given ID.
- * @param id the ID.
+ * Removes a payload-type element defined by XEP-0167: Jingle
+ * RTP Sessions from this channel.
+ *
+ * @param payloadType the payload-type element to be removed
+ * from this channel
+ * @return true if the list of payload-type elements
+ * associated with this channel has been modified as part of
+ * the method call; otherwise, false
*/
- public ChannelBundle(String id)
+ public boolean removePayloadType(PayloadTypePacketExtension payloadType)
{
- this.id = id;
+ return payloadTypes.remove(payloadType);
}
/**
- * Returns the transport element of this ChannelBundle.
- * @return the transport element of this ChannelBundle.
+ * Removes a SourcePacketExtension from the list of sources of
+ * this channel.
+ *
+ * @param source the SourcePacketExtension to remove from the
+ * list of sources of this channel
+ * @return true if the list of sources of this channel changed
+ * as a result of the execution of the method; otherwise, false
*/
- public IceUdpTransportPacketExtension getTransport()
+ public synchronized boolean removeSource(SourcePacketExtension source)
{
- return transport;
+ return sources.remove(source);
}
/**
- * Sets the transport element of this ChannelBundle.
- * @param transport the transport to set.
+ * Removes a specific (RTP) SSRC from the list of SSRCs seen/received on
+ * this Channel. Invoked by the Jitsi Videobridge server, not
+ * its clients.
+ *
+ * @param ssrc the (RTP) SSRC to be removed from the list of SSRCs
+ * seen/received on this Channel
+ * @return true if the list of SSRCs seen/received on this
+ * Channel has been modified as part of the method call;
+ * otherwise, false
*/
- public void setTransport(IceUdpTransportPacketExtension transport)
+ public synchronized boolean removeSSRC(int ssrc)
{
- this.transport = transport;
+ if (ssrcs.length == 1)
+ {
+ if (ssrcs[0] == ssrc)
+ {
+ ssrcs = NO_SSRCS;
+ return true;
+ }
+ else
+ return false;
+ }
+ else
+ {
+ for (int i = 0; i < ssrcs.length; i++)
+ {
+ if (ssrcs[i] == ssrc)
+ {
+ int[] newSSRCs = new int[ssrcs.length - 1];
+
+ if (i != 0)
+ System.arraycopy(ssrcs, 0, newSSRCs, 0, i);
+ if (i != newSSRCs.length)
+ {
+ System.arraycopy(
+ ssrcs, i + 1,
+ newSSRCs, i,
+ newSSRCs.length - i);
+ }
+ ssrcs = newSSRCs;
+ return true;
+ }
+ }
+ return false;
+ }
}
/**
- * Returns the ID of this ChannelBundle.
- * @return the ID of this ChannelBundle.
+ * Sets the direction of this Channel
+ *
+ * @param direction the MediaDirection to set the
+ * direction of this Channel to.
*/
- public String getId()
+ public void setDirection(MediaDirection direction)
{
- return id;
+ this.direction = direction;
}
/**
- * Sets the ID of this ChannelBundle.
- * @param id the ID to set.
+ * Sets the IP address (as a String value) of the host on which
+ * the channel represented by this instance has been allocated.
+ *
+ * @param host a String value which represents the IP address
+ * of the host on which the channel represented by this
+ * instance has been allocated
+ *
+ * @deprecated The method is supported for the purposes of compatibility
+ * with legacy versions of Jitsi and Jitsi Videobridge.
*/
- public void setId(String id)
+ @Deprecated
+ public void setHost(String host)
{
- this.id = id;
+ this.host = host;
}
/**
- * Appends an XML representation of this ChannelBundle to
- * xml.
- * @param xml the StringBuilder to append to.
+ * Sets the maximum number of video RTP streams to be sent from Jitsi
+ * Videobridge to the endpoint associated with this video
+ * Channel.
+ *
+ * @param lastN the maximum number of video RTP streams to be sent from
+ * Jitsi Videobridge to the endpoint associated with this video
+ * Channel
*/
- public void toXML(StringBuilder xml)
+ public void setLastN(Integer lastN)
{
- xml.append('<').append(ELEMENT_NAME).append(' ')
- .append(ID_ATTR_NAME).append("='").append(id).append('\'');
-
- if (transport != null)
- {
- xml.append('>');
- xml.append(transport.toXML());
- xml.append("").append(ELEMENT_NAME).append('>');
- }
- else
- {
- xml.append(" />");
- }
+ this.lastN = lastN;
}
- }
- /**
- * Represents a channel included into a content of a Jitsi
- * Videobridge conference IQ.
- */
- public static class Channel
- extends ChannelCommon
- {
/**
- * The name of the XML attribute of a channel which represents
- * its direction.
- */
- public static final String DIRECTION_ATTR_NAME = "direction";
-
- /**
- * The XML element name of a channel of a content of a
- * Jitsi Videobridge conference IQ.
+ * Sets the target quality of the simulcast substreams to be sent from
+ * Jitsi Videobridge to the endpoint associated with this video
+ * Channel.
+ *
+ * @param simulcastLayer the target quality of the simulcast substreams
+ * to be sent from Jitsi Videobridge to the endpoint associated with
+ * this video Channel.
*/
- public static final String ELEMENT_NAME = "channel";
+ public void setReceivingSimulcastLayer(Integer simulcastLayer)
+ {
+ this.receivingSimulcastLayer = simulcastLayer;
+ }
/**
- * The XML name of the host attribute of a channel of
- * a content of a conference IQ which represents the
- * value of the host property of
- * ColibriConferenceIQ.Channel.
+ * Sets the port which has been allocated to this channel for
+ * the purposes of transmitting RTCP packets.
*
- * @deprecated The attribute is supported for the purposes of
- * compatibility with legacy versions of Jitsi and Jitsi Videobridge.
+ * @param rtcpPort the port which has been allocated to this
+ * channel for the purposes of transmitting RTCP packets
+ *
+ * @deprecated The method is supported for the purposes of compatibility
+ * with legacy versions of Jitsi and Jitsi Videobridge.
*/
@Deprecated
- public static final String HOST_ATTR_NAME = "host";
-
- /**
- * The XML name of the id attribute of a channel of a
- * content of a conference IQ which represents the
- * value of the id property of
- * ColibriConferenceIQ.Channel.
- */
- public static final String ID_ATTR_NAME = "id";
+ public void setRTCPPort(int rtcpPort)
+ {
+ this.rtcpPort = rtcpPort;
+ }
/**
- * The XML name of the last-n attribute of a video
- * channel which specifies the maximum number of video RTP
- * streams to be sent from Jitsi Videobridge to the endpoint associated
- * with the video channel. The value of the last-n
- * attribute is a positive number.
+ * Sets the type of RTP-level relay (in the terms specified by RFC 3550
+ * "RTP: A Transport Protocol for Real-Time Applications" in
+ * section 2.3 "Mixers and Translators") used for this
+ * Channel.
+ *
+ * @param rtpLevelRelayType the type of RTP-level relay used for
+ * this Channel
*/
- public static final String LAST_N_ATTR_NAME = "last-n";
+ public void setRTPLevelRelayType(RTPLevelRelayType rtpLevelRelayType)
+ {
+ this.rtpLevelRelayType = rtpLevelRelayType;
+ }
/**
- * The XML name of the rtcpport attribute of a channel
- * of a content of a conference IQ which represents
- * the value of the rtcpPort property of
- * ColibriConferenceIQ.Channel.
+ * Sets the type of RTP-level relay (in the terms specified by RFC 3550
+ * "RTP: A Transport Protocol for Real-Time Applications" in
+ * section 2.3 "Mixers and Translators") used for this
+ * Channel.
*
- * @deprecated The attribute is supported for the purposes of
- * compatibility with legacy versions of Jitsi and Jitsi Videobridge.
+ * @param s the type of RTP-level relay used for this Channel
*/
- @Deprecated
- public static final String RTCP_PORT_ATTR_NAME = "rtcpport";
-
- public static final String RTP_LEVEL_RELAY_TYPE_ATTR_NAME
- = "rtp-level-relay-type";
+ public void setRTPLevelRelayType(String s)
+ {
+ setRTPLevelRelayType(RTPLevelRelayType.parseRTPLevelRelayType(s));
+ }
/**
- * The XML name of the rtpport attribute of a channel
- * of a content of a conference IQ which represents
- * the value of the rtpPort property of
- * ColibriConferenceIQ.Channel.
+ * Sets the port which has been allocated to this channel for
+ * the purposes of transmitting RTP packets.
*
- * @deprecated The attribute is supported for the purposes of
- * compatibility with legacy versions of Jitsi and Jitsi Videobridge.
+ * @param rtpPort the port which has been allocated to this
+ * channel for the purposes of transmitting RTP packets
+ *
+ * @deprecated The method is supported for the purposes of compatibility
+ * with legacy versions of Jitsi and Jitsi Videobridge.
*/
@Deprecated
- public static final String RTP_PORT_ATTR_NAME = "rtpport";
+ public void setRTPPort(int rtpPort)
+ {
+ this.rtpPort = rtpPort;
+ }
/**
- * The name of the XML element which is a child of the <channel>
- * element and which identifies/specifies an (RTP) SSRC which has been
- * seen/received on the respective Channel.
+ * Sets the list of (RTP) SSRCs seen/received on this Channel.
+ *
+ * @param ssrcs the list of (RTP) SSRCs to be set as seen/received on
+ * this Channel
*/
- public static final String SSRC_ELEMENT_NAME = "ssrc";
+ public void setSSRCs(int[] ssrcs)
+ {
+ /*
+ * TODO Make sure that the SSRCs set on this instance do not contain
+ * duplicates.
+ */
+ this.ssrcs
+ = ((ssrcs == null) || (ssrcs.length == 0))
+ ? NO_SSRCS
+ : ssrcs.clone();
+ }
+ }
+ /**
+ * Represents a "channel-bundle" element.
+ */
+ public static class ChannelBundle
+ {
/**
- * The direction of the channel represented by this instance.
+ * The name of the "channel-bundle" element.
*/
- private MediaDirection direction;
+ public static final String ELEMENT_NAME = "channel-bundle";
/**
- * The host of the channel represented by this instance.
- *
- * @deprecated The field is supported for the purposes of compatibility
- * with legacy versions of Jitsi and Jitsi Videobridge.
+ * The name of the "id" attribute.
*/
- @Deprecated
- private String host;
+ public static final String ID_ATTR_NAME = "id";
/**
- * The ID of the channel represented by this instance.
+ * The ID of this ChannelBundle.
*/
private String id;
/**
- * The maximum number of video RTP streams to be sent from Jitsi
- * Videobridge to the endpoint associated with this video
- * Channel.
- */
- private Integer lastN;
-
- /**
- * The payload-type elements defined by XEP-0167: Jingle RTP
- * Sessions associated with this channel.
+ * The transport element of this ChannelBundle.
*/
- private final List payloadTypes
- = new ArrayList();
+ private IceUdpTransportPacketExtension transport;
/**
- * The RTCP port of the channel represented by this instance.
- *
- * @deprecated The field is supported for the purposes of compatibility
- * with legacy versions of Jitsi and Jitsi Videobridge.
+ * Initializes a new ChannelBundle with the given ID.
+ * @param id the ID.
*/
- @Deprecated
- private int rtcpPort;
+ public ChannelBundle(String id)
+ {
+ this.id = id;
+ }
/**
- * The type of RTP-level relay (in the terms specified by RFC 3550
- * "RTP: A Transport Protocol for Real-Time Applications" in
- * section 2.3 "Mixers and Translators") used for this
- * Channel.
+ * Returns the ID of this ChannelBundle.
+ * @return the ID of this ChannelBundle.
*/
- private RTPLevelRelayType rtpLevelRelayType;
+ public String getId()
+ {
+ return id;
+ }
/**
- * The RTP port of the channel represented by this instance.
- *
- * @deprecated The field is supported for the purposes of compatibility
- * with legacy versions of Jitsi and Jitsi Videobridge.
+ * Returns the transport element of this ChannelBundle.
+ * @return the transport element of this ChannelBundle.
*/
- @Deprecated
- private int rtpPort;
+ public IceUdpTransportPacketExtension getTransport()
+ {
+ return transport;
+ }
/**
- * The SourcePacketExtensions of this channel.
+ * Sets the ID of this ChannelBundle.
+ * @param id the ID to set.
*/
- private final List sources
- = new LinkedList();
+ public void setId(String id)
+ {
+ this.id = id;
+ }
/**
- * The list of (RTP) SSRCs which have been seen/received on this
- * Channel by now. These may exclude SSRCs which are no longer
- * active. Set by the Jitsi Videobridge server, not its clients.
+ * Sets the transport element of this ChannelBundle.
+ * @param transport the transport to set.
*/
- private int[] ssrcs = NO_SSRCS;
-
- /** Initializes a new Channel instance. */
- public Channel()
+ public void setTransport(IceUdpTransportPacketExtension transport)
{
- super(Channel.ELEMENT_NAME);
+ this.transport = transport;
}
/**
- * Adds a payload-type element defined by XEP-0167: Jingle RTP
- * Sessions to this channel.
- *
- * @param payloadType the payload-type element to be added to
- * this channel
- * @return true if the list of payload-type elements
- * associated with this channel has been modified as part of
- * the method call; otherwise, false
- * @throws NullPointerException if the specified payloadType is
- * null
+ * Appends an XML representation of this ChannelBundle to
+ * xml.
+ * @param xml the StringBuilder to append to.
*/
- public boolean addPayloadType(PayloadTypePacketExtension payloadType)
+ public void toXML(StringBuilder xml)
{
- if (payloadType == null)
- throw new NullPointerException("payloadType");
-
- // Make sure that the COLIBRI namespace is used.
- payloadType.setNamespace(null);
- for (ParameterPacketExtension p : payloadType.getParameters())
- p.setNamespace(null);
+ xml.append('<').append(ELEMENT_NAME).append(' ')
+ .append(ID_ATTR_NAME).append("='").append(id).append('\'');
- return
- payloadTypes.contains(payloadType)
- ? false
- : payloadTypes.add(payloadType);
+ if (transport != null)
+ {
+ xml.append('>');
+ xml.append(transport.toXML());
+ xml.append("").append(ELEMENT_NAME).append('>');
+ }
+ else
+ {
+ xml.append(" />");
+ }
}
+ }
+ /**
+ * Class contains common code for both Channel and
+ * SctpConnection IQ classes.
+ *
+ * @author Pawel Domas
+ */
+ public static abstract class ChannelCommon
+ {
/**
- * Adds a SourcePacketExtension to the list of sources of this
- * channel.
- *
- * @param source the SourcePacketExtension to add to the list
- * of sources of this channel
- * @return true if the list of sources of this channel changed
- * as a result of the execution of the method; otherwise, false
+ * The name of the "channel-bundle-id" attribute.
*/
- public synchronized boolean addSource(SourcePacketExtension source)
- {
- if (source == null)
- throw new NullPointerException("source");
+ public static final String CHANNEL_BUNDLE_ID_ATTR_NAME
+ = "channel-bundle-id";
- return sources.contains(source) ? false : sources.add(source);
- }
+ /**
+ * The XML name of the endpoint attribute which specifies the
+ * optional identifier of the endpoint of the conference participant
+ * associated with a channel. The value of the
+ * endpoint attribute is an opaque String from the
+ * point of view of Jitsi Videobridge.
+ */
+ public static final String ENDPOINT_ATTR_NAME = "endpoint";
/**
- * Adds a specific (RTP) SSRC to the list of SSRCs seen/received on this
- * Channel. Invoked by the Jitsi Videobridge server, not its
- * clients.
- *
- * @param ssrc the (RTP) SSRC to be added to the list of SSRCs
- * seen/received on this Channel
- * @return true if the list of SSRCs seen/received on this
- * Channel has been modified as part of the method call;
- * otherwise, false
+ * The XML name of the expire attribute of a channel
+ * of a content of a conference IQ which represents
+ * the value of the expire property of
+ * ColibriConferenceIQ.Channel.
*/
- public synchronized boolean addSSRC(int ssrc)
- {
- // contains
- for (int i = 0; i < ssrcs.length; i++)
- if (ssrcs[i] == ssrc)
- return false;
+ public static final String EXPIRE_ATTR_NAME = "expire";
- // add
- int[] newSSRCs = new int[ssrcs.length + 1];
+ /**
+ * The value of the expire property of
+ * ColibriConferenceIQ.Channel which indicates that no actual
+ * value has been specified for the property in question.
+ */
+ public static final int EXPIRE_NOT_SPECIFIED = -1;
- System.arraycopy(ssrcs, 0, newSSRCs, 0, ssrcs.length);
- newSSRCs[ssrcs.length] = ssrc;
- ssrcs = newSSRCs;
- return true;
- }
+ /**
+ * The XML name of the id attribute of a channel of a
+ * content of a conference IQ which represents the
+ * value of the id property of
+ * ColibriConferenceIQ.Channel.
+ */
+ public static final String ID_ATTR_NAME = "id";
/**
- * Gets the direction of this Channel.
- *
- * @return the direction of this Channel.
+ * The XML name of the initiator attribute of a
+ * channel of a content of a conference IQ
+ * which represents the value of the initiator property of
+ * ColibriConferenceIQ.Channel.
*/
- public MediaDirection getDirection()
- {
- return (direction == null) ? MediaDirection.SENDRECV : direction;
- }
+ public static final String INITIATOR_ATTR_NAME = "initiator";
/**
- * Gets the IP address (as a String value) of the host on which
- * the channel represented by this instance has been allocated.
- *
- * @return a String value which represents the IP address of
- * the host on which the channel represented by this instance
- * has been allocated
- *
- * @deprecated The method is supported for the purposes of compatibility
- * with legacy versions of Jitsi and Jitsi Videobridge.
+ * The channel-bundle-id attribute of this CommonChannel.
*/
- @Deprecated
- public String getHost()
- {
- return host;
- }
+ private String channelBundleId = null;
+
+ /**
+ * XML element name.
+ */
+ private String elementName;
/**
- * Gets the ID of the channel represented by this instance.
- *
- * @return the ID of the channel represented by this instance
+ * The identifier of the endpoint of the conference participant
+ * associated with this Channel.
*/
- public String getID()
- {
- return id;
- }
+ private String endpoint;
/**
- * Gets the maximum number of video RTP streams to be sent from Jitsi
- * Videobridge to the endpoint associated with this video
- * Channel.
- *
- * @return the maximum number of video RTP streams to be sent from Jitsi
- * Videobridge to the endpoint associated with this video
- * Channel
+ * The number of seconds of inactivity after which the channel
+ * represented by this instance expires.
*/
- public Integer getLastN()
- {
- return lastN;
- }
+ private int expire = EXPIRE_NOT_SPECIFIED;
/**
- * Gets a list of payload-type elements defined by XEP-0167:
- * Jingle RTP Sessions added to this channel.
- *
- * @return an unmodifiable List of payload-type
- * elements defined by XEP-0167: Jingle RTP Sessions added to this
- * channel
+ * The ID of the channel represented by this instance.
*/
- public List getPayloadTypes()
- {
- return Collections.unmodifiableList(payloadTypes);
- }
+ private String id;
/**
- * Gets the port which has been allocated to this channel for
- * the purposes of transmitting RTCP packets.
- *
- * @return the port which has been allocated to this channel
- * for the purposes of transmitting RTCP packets
- *
- * @deprecated The method is supported for the purposes of compatibility
- * with legacy versions of Jitsi and Jitsi Videobridge.
+ * The indicator which determines whether the conference focus is the
+ * initiator/offerer (as opposed to the responder/answerer) of the media
+ * negotiation associated with this instance.
*/
- @Deprecated
- public int getRTCPPort()
- {
- return rtcpPort;
- }
+ private Boolean initiator;
+
+ private IceUdpTransportPacketExtension transport;
/**
- * Gets the type of RTP-level relay (in the terms specified by RFC 3550
- * "RTP: A Transport Protocol for Real-Time Applications" in
- * section 2.3 "Mixers and Translators") used for this
- * Channel.
- *
- * @return the type of RTP-level relay used for this Channel
+ * Initializes this class with given XML elementName.
+ * @param elementName XML element name to be used for producing XML
+ * representation of derived IQ class.
*/
- public RTPLevelRelayType getRTPLevelRelayType()
+ protected ChannelCommon(String elementName)
{
- return rtpLevelRelayType;
+ this.elementName = elementName;
}
/**
- * Gets the port which has been allocated to this channel for
- * the purposes of transmitting RTP packets.
- *
- * @return the port which has been allocated to this channel
- * for the purposes of transmitting RTP packets
- *
- * @deprecated The method is supported for the purposes of compatibility
- * with legacy versions of Jitsi and Jitsi Videobridge.
+ * Get the channel-bundle-id attribute of this CommonChannel.
+ * @return the channel-bundle-id attribute of this
+ * CommonChannel.
*/
- @Deprecated
- public int getRTPPort()
+ public String getChannelBundleId()
{
- return rtpPort;
+ return channelBundleId;
}
/**
- * Gets the list of SourcePacketExtensionss which represent the
- * sources of this channel.
+ * Gets the identifier of the endpoint of the conference participant
+ * associated with this Channel.
*
- * @return a List of SourcePacketExtensions which
- * represent the sources of this channel
+ * @return the identifier of the endpoint of the conference participant
+ * associated with this Channel
*/
- public synchronized List getSources()
+ public String getEndpoint()
{
- return new ArrayList(sources);
+ return endpoint;
}
/**
- * Gets (a copy of) the list of (RTP) SSRCs seen/received on this
- * Channel.
+ * Gets the number of seconds of inactivity after which the
+ * channel represented by this instance expires.
*
- * @return an array of ints which represents (a copy of) the
- * list of (RTP) SSRCs seen/received on this Channel
+ * @return the number of seconds of inactivity after which the
+ * channel represented by this instance expires
*/
- public synchronized int[] getSSRCs()
+ public int getExpire()
{
- return (ssrcs.length == 0) ? NO_SSRCS : ssrcs.clone();
+ return expire;
}
/**
- * Removes a payload-type element defined by XEP-0167: Jingle
- * RTP Sessions from this channel.
+ * Gets the ID of the channel represented by this instance.
*
- * @param payloadType the payload-type element to be removed
- * from this channel
- * @return true if the list of payload-type elements
- * associated with this channel has been modified as part of
- * the method call; otherwise, false
+ * @return the ID of the channel represented by this instance
*/
- public boolean removePayloadType(PayloadTypePacketExtension payloadType)
+ public String getID()
{
- return payloadTypes.remove(payloadType);
+ return id;
}
- /**
- * Removes a SourcePacketExtension from the list of sources of
- * this channel.
- *
- * @param source the SourcePacketExtension to remove from the
- * list of sources of this channel
- * @return true if the list of sources of this channel changed
- * as a result of the execution of the method; otherwise, false
- */
- public synchronized boolean removeSource(SourcePacketExtension source)
+ public IceUdpTransportPacketExtension getTransport()
{
- return sources.remove(source);
+ return transport;
}
/**
- * Removes a specific (RTP) SSRC from the list of SSRCs seen/received on
- * this Channel. Invoked by the Jitsi Videobridge server, not
- * its clients.
- *
- * @param ssrc the (RTP) SSRC to be removed from the list of SSRCs
- * seen/received on this Channel
- * @return true if the list of SSRCs seen/received on this
- * Channel has been modified as part of the method call;
- * otherwise, false
+ * Indicates whether there are some contents that should be printed as
+ * child elements of this IQ. If true is returned
+ * {@link #printContent(StringBuilder)} method will be called when
+ * XML representation of this IQ is being constructed.
+ * @return true if there are content to be printed as child
+ * elements of this IQ or false otherwise.
*/
- public synchronized boolean removeSSRC(int ssrc)
- {
- if (ssrcs.length == 1)
- {
- if (ssrcs[0] == ssrc)
- {
- ssrcs = NO_SSRCS;
- return true;
- }
- else
- return false;
- }
- else
- {
- for (int i = 0; i < ssrcs.length; i++)
- {
- if (ssrcs[i] == ssrc)
- {
- int[] newSSRCs = new int[ssrcs.length - 1];
-
- if (i != 0)
- System.arraycopy(ssrcs, 0, newSSRCs, 0, i);
- if (i != newSSRCs.length)
- {
- System.arraycopy(
- ssrcs, i + 1,
- newSSRCs, i,
- newSSRCs.length - i);
- }
- ssrcs = newSSRCs;
- return true;
- }
- }
- return false;
- }
- }
+ protected abstract boolean hasContent();
/**
- * Sets the direction of this Channel
+ * Gets the indicator which determines whether the conference focus is
+ * the initiator/offerer (as opposed to the responder/answerer) of the
+ * media negotiation associated with this instance.
*
- * @param direction the MediaDirection to set the
- * direction of this Channel to.
+ * @return {@link Boolean#TRUE} if the conference focus is the
+ * initiator/offerer of the media negotiation associated with this
+ * instance, {@link Boolean#FALSE} if the conference focus is the
+ * responder/answerer or null if the initiator state
+ * is unspecified
*/
- public void setDirection(MediaDirection direction)
+ public Boolean isInitiator()
{
- this.direction = direction;
+ return initiator;
}
/**
- * Sets the IP address (as a String value) of the host on which
- * the channel represented by this instance has been allocated.
- *
- * @param host a String value which represents the IP address
- * of the host on which the channel represented by this
- * instance has been allocated
- *
- * @deprecated The method is supported for the purposes of compatibility
- * with legacy versions of Jitsi and Jitsi Videobridge.
+ * Derived class implements this method in order to print additional
+ * attributes to main XML element.
+ * @param xml StringBuilder to which the XML
+ * String representation of this Channel
+ * is to be appended
*/
- @Deprecated
- public void setHost(String host)
- {
- this.host = host;
- }
+ protected abstract void printAttributes(StringBuilder xml);
/**
- * Sets the ID of the channel represented by this instance.
+ * Implement in order to print content child elements of this IQ using
+ * given StringBuilder. Called during construction of XML
+ * representation if {@link #hasContent()} returns true.
*
- * @param id the ID of the channel represented by this instance
+ * @param xml the StringBuilder to which the XML
+ * String representation of this Channel
+ * is to be appended.
*/
- public void setID(String id)
- {
- this.id = id;
- }
+ protected abstract void printContent(StringBuilder xml);
/**
- * Sets the maximum number of video RTP streams to be sent from Jitsi
- * Videobridge to the endpoint associated with this video
- * Channel.
- *
- * @param lastN the maximum number of video RTP streams to be sent from
- * Jitsi Videobridge to the endpoint associated with this video
- * Channel
+ * Sets the channel-bundle-id attribute of this CommonChannel.
+ * @param channelBundleId the value to set.
*/
- public void setLastN(Integer lastN)
+ public void setChannelBundleId(String channelBundleId)
{
- this.lastN = lastN;
+ this.channelBundleId = channelBundleId;
}
/**
- * Sets the port which has been allocated to this channel for
- * the purposes of transmitting RTCP packets.
- *
- * @param rtcpPort the port which has been allocated to this
- * channel for the purposes of transmitting RTCP packets
+ * Sets the identifier of the endpoint of the conference participant
+ * associated with this Channel.
*
- * @deprecated The method is supported for the purposes of compatibility
- * with legacy versions of Jitsi and Jitsi Videobridge.
+ * @param endpoint the identifier of the endpoint of the conference
+ * participant associated with this Channel
*/
- @Deprecated
- public void setRTCPPort(int rtcpPort)
+ public void setEndpoint(String endpoint)
{
- this.rtcpPort = rtcpPort;
+ this.endpoint = endpoint;
}
/**
- * Sets the type of RTP-level relay (in the terms specified by RFC 3550
- * "RTP: A Transport Protocol for Real-Time Applications" in
- * section 2.3 "Mixers and Translators") used for this
- * Channel.
+ * Sets the number of seconds of inactivity after which the
+ * channel represented by this instance expires.
*
- * @param rtpLevelRelayType the type of RTP-level relay used for
- * this Channel
+ * @param expire the number of seconds of activity after which the
+ * channel represented by this instance expires
+ * @throws IllegalArgumentException if the value of the specified
+ * expire is other than {@link #EXPIRE_NOT_SPECIFIED} and
+ * negative
*/
- public void setRTPLevelRelayType(RTPLevelRelayType rtpLevelRelayType)
+ public void setExpire(int expire)
{
- this.rtpLevelRelayType = rtpLevelRelayType;
+ if ((expire != EXPIRE_NOT_SPECIFIED) && (expire < 0))
+ throw new IllegalArgumentException("expire");
+
+ this.expire = expire;
}
- /**
- * Sets the type of RTP-level relay (in the terms specified by RFC 3550
- * "RTP: A Transport Protocol for Real-Time Applications" in
- * section 2.3 "Mixers and Translators") used for this
- * Channel.
+ /*
+ * Sets the ID of the channel represented by this instance.
*
- * @param s the type of RTP-level relay used for this Channel
+ * @param id the ID of the channel represented by this instance
*/
- public void setRTPLevelRelayType(String s)
+ public void setID(String id)
{
- setRTPLevelRelayType(RTPLevelRelayType.parseRTPLevelRelayType(s));
+ this.id = id;
}
/**
- * Sets the port which has been allocated to this channel for
- * the purposes of transmitting RTP packets.
- *
- * @param rtpPort the port which has been allocated to this
- * channel for the purposes of transmitting RTP packets
+ * Sets the indicator which determines whether the conference focus is
+ * the initiator/offerer (as opposed to the responder/answerer) of the
+ * media negotiation associated with this instance.
*
- * @deprecated The method is supported for the purposes of compatibility
- * with legacy versions of Jitsi and Jitsi Videobridge.
+ * @param initiator {@link Boolean#TRUE} if the conference focus is the
+ * initiator/offerer of the media negotiation associated with this
+ * instance, {@link Boolean#FALSE} if the conference focus is the
+ * responder/answerer or null if the initiator state
+ * is to be unspecified
*/
- @Deprecated
- public void setRTPPort(int rtpPort)
+ public void setInitiator(Boolean initiator)
{
- this.rtpPort = rtpPort;
+ this.initiator = initiator;
+ }
+
+ public void setTransport(IceUdpTransportPacketExtension transport)
+ {
+ this.transport = transport;
}
/**
- * Sets the list of (RTP) SSRCs seen/received on this Channel.
+ * Appends the XML String representation of this
+ * Channel to a specific StringBuilder.
*
- * @param ssrcs the list of (RTP) SSRCs to be set as seen/received on
- * this Channel
+ * @param xml the StringBuilder to which the XML
+ * String representation of this Channel is to be
+ * appended
*/
- public void setSSRCs(int[] ssrcs)
+ public void toXML(StringBuilder xml)
{
- /*
- * TODO Make sure that the SSRCs set on this instance do not contain
- * duplicates.
- */
- this.ssrcs
- = ((ssrcs == null) || (ssrcs.length == 0))
- ? NO_SSRCS
- : ssrcs.clone();
- }
+ xml.append('<').append(elementName);
- @Override
- protected void printAttributes(StringBuilder xml)
- {
- // direction
- MediaDirection direction = getDirection();
+ // endpoint
+ String endpoint = getEndpoint();
- if ((direction != null) && (direction != MediaDirection.SENDRECV))
+ if (endpoint != null)
{
- xml.append(' ').append(DIRECTION_ATTR_NAME).append("='")
- .append(direction.toString()).append('\'');
+ xml.append(' ').append(ENDPOINT_ATTR_NAME).append("='")
+ .append(endpoint).append('\'');
}
- // host
- String host = getHost();
+ // expire
+ int expire = getExpire();
- if (host != null)
+ if (expire >= 0)
{
- xml.append(' ').append(HOST_ATTR_NAME).append("='").append(host)
- .append('\'');
+ xml.append(' ').append(EXPIRE_ATTR_NAME).append("='")
+ .append(expire).append('\'');
}
// id
@@ -1348,79 +1463,43 @@ protected void printAttributes(StringBuilder xml)
if (id != null)
{
- xml.append(' ').append(ID_ATTR_NAME).append("='").append(id)
- .append('\'');
- }
-
- // lastN
- Integer lastN = getLastN();
-
- if (lastN != null)
- {
- xml.append(' ').append(LAST_N_ATTR_NAME).append("='")
- .append(lastN).append('\'');
+ xml.append(' ').append(ID_ATTR_NAME).append("='")
+ .append(id).append('\'');
}
- // rtcpPort
- int rtcpPort = getRTCPPort();
+ // initiator
+ Boolean initiator = isInitiator();
- if (rtcpPort > 0)
+ if (initiator != null)
{
- xml.append(' ').append(RTCP_PORT_ATTR_NAME).append("='")
- .append(rtcpPort).append('\'');
+ xml.append(' ').append(INITIATOR_ATTR_NAME).append("='")
+ .append(initiator).append('\'');
}
- // rtpLevelRelayType
- RTPLevelRelayType rtpLevelRelayType = getRTPLevelRelayType();
-
- if (rtpLevelRelayType != null)
+ String channelBundleId = getChannelBundleId();
+ if (channelBundleId != null)
{
- xml.append(' ').append(RTP_LEVEL_RELAY_TYPE_ATTR_NAME)
- .append("='").append(rtpLevelRelayType).append('\'');
+ xml.append(' ').append(CHANNEL_BUNDLE_ID_ATTR_NAME)
+ .append("='").append(channelBundleId).append('\'');
}
- // rtpPort
- int rtpPort = getRTPPort();
+ // Print derived class attributes
+ printAttributes(xml);
- if (rtpPort > 0)
+ IceUdpTransportPacketExtension transport = getTransport();
+ boolean hasTransport = (transport != null);
+ if (hasTransport || hasContent())
{
- xml.append(' ').append(RTP_PORT_ATTR_NAME).append("='")
- .append(rtpPort).append('\'');
+ xml.append('>');
+ if(hasContent())
+ printContent(xml);
+ if (hasTransport)
+ xml.append(transport.toXML());
+ xml.append("").append(elementName).append('>');
}
- }
-
- @Override
- protected boolean hasContent()
- {
- List payloadTypes = getPayloadTypes();
- boolean hasPayloadTypes = !payloadTypes.isEmpty();
- List sources = getSources();
- boolean hasSources = !sources.isEmpty();
- int[] ssrcs = getSSRCs();
- boolean hasSSRCs = (ssrcs.length != 0);
-
- return hasPayloadTypes || hasSources || hasSSRCs;
- }
-
- @Override
- protected void printContent(StringBuilder xml)
- {
- List payloadTypes = getPayloadTypes();
- List sources = getSources();
- int[] ssrcs = getSSRCs();
-
- for (PayloadTypePacketExtension payloadType : payloadTypes)
- xml.append(payloadType.toXML());
-
- for (SourcePacketExtension source : sources)
- xml.append(source.toXML());
-
- for (int i = 0; i < ssrcs.length; i++)
+ else
{
- xml.append('<').append(SSRC_ELEMENT_NAME).append('>')
- .append(Long.toString(ssrcs[i] & 0xFFFFFFFFL))
- .append("").append(SSRC_ELEMENT_NAME)
- .append('>');
+ xml.append(" />");
}
}
}
@@ -1450,6 +1529,11 @@ public static class Content
*/
private final List channels = new LinkedList();
+ /**
+ * The name of the content represented by this instance.
+ */
+ private String name;
+
/**
* The list of {@link SctpConnection}s included into this
* content of a conference IQ.
@@ -1457,11 +1541,6 @@ public static class Content
private final List sctpConnections
= new LinkedList();
- /**
- * The name of the content represented by this instance.
- */
- private String name;
-
/**
* Initializes a new Content instance without a name and
* channels.
@@ -1501,6 +1580,26 @@ public boolean addChannel(Channel channel)
return channels.contains(channel) ? false : channels.add(channel);
}
+ /**
+ * Adds a specific SctpConnection to the list of
+ * SctpConnections included into this Content.
+ *
+ * @param conn the SctpConnection to be included into this
+ * Content
+ * @return true if the list of SctpConnections
+ * included into this Content was modified as a result of
+ * the execution of the method; otherwise, false
+ * @throws NullPointerException if the specified conn is
+ * null
+ */
+ public boolean addSctpConnection(SctpConnection conn)
+ {
+ if(conn == null)
+ throw new NullPointerException("Sctp connection");
+
+ return !sctpConnections.contains(conn) && sctpConnections.add(conn);
+ }
+
/**
* Gets the Channel at a specific index/position within the
* list of Channels included in this Content.
@@ -1530,8 +1629,25 @@ public Channel getChannel(int channelIndex)
public Channel getChannel(String channelID)
{
for (Channel channel : getChannels())
+ {
if (channelID.equals(channel.getID()))
return channel;
+ }
+ return null;
+ }
+
+ /**
+ * Finds an SCTP connection identified by given connectionID.
+ * @param connectionID the ID of the SCTP connection to find.
+ * @return SctpConnection instance identified by given ID
+ * or null if no such connection is contained in
+ * this IQ.
+ */
+ public SctpConnection getSctpConnection(String connectionID)
+ {
+ for (SctpConnection conn : getSctpConnections())
+ if (connectionID.equals(conn.getID()))
+ return conn;
return null;
}
@@ -1551,44 +1667,12 @@ public int getChannelCount()
* Gets a list of the Channel included into/associated with
* this Content.
*
- * @return an unmodifiable List of the Channels
- * included into/associated with this Content
- */
- public List getChannels()
- {
- return Collections.unmodifiableList(channels);
- }
-
- /**
- * Adds a specific SctpConnection to the list of
- * SctpConnections included into this Content.
- *
- * @param conn the SctpConnection to be included into this
- * Content
- * @return true if the list of SctpConnections
- * included into this Content was modified as a result of
- * the execution of the method; otherwise, false
- * @throws NullPointerException if the specified conn is
- * null
- */
- public boolean addSctpConnection(SctpConnection conn)
- {
- if(conn == null)
- throw new NullPointerException("Sctp connection");
-
- return !sctpConnections.contains(conn) && sctpConnections.add(conn);
- }
-
- /**
- * Gets a list of the SctpConnections included into/associated
- * with this Content.
- *
- * @return an unmodifiable List of the SctpConnections
+ * @return an unmodifiable List of the Channels
* included into/associated with this Content
*/
- public List getSctpConnections()
+ public List getChannels()
{
- return Collections.unmodifiableList(sctpConnections);
+ return Collections.unmodifiableList(channels);
}
/**
@@ -1601,6 +1685,18 @@ public String getName()
return name;
}
+ /**
+ * Gets a list of the SctpConnections included into/associated
+ * with this Content.
+ *
+ * @return an unmodifiable List of the SctpConnections
+ * included into/associated with this Content
+ */
+ public List getSctpConnections()
+ {
+ return Collections.unmodifiableList(sctpConnections);
+ }
+
/**
* Removes a specific Channel from the list of
* Channels included into this Content.
@@ -1663,94 +1759,95 @@ public void toXML(StringBuilder xml)
xml.append("").append(ELEMENT_NAME).append('>');
}
}
+
+ /**
+ * Removes given SCTP connection from this IQ.
+ * @param connection the SCTP connection instance to be removed.
+ * @return true if given connection was contained in
+ * this IQ and has been removed successfully.
+ */
+ public boolean removeSctpConnection(SctpConnection connection)
+ {
+ return sctpConnections.remove(connection);
+ }
}
/**
- * Represents a SCTP connection included into a content
- * of a Jitsi Videobridge conference IQ.
- *
- * @author Pawel Domas
+ * Represents an 'endpoint' element.
*/
- public static class SctpConnection
- extends ChannelCommon
+ public static class Endpoint
{
/**
- * The XML element name of a content of a Jitsi Videobridge
- * conference IQ.
+ * The name of the 'displayname' attribute.
*/
- public static final String ELEMENT_NAME = "sctpconnection";
+ public static final String DISPLAYNAME_ATTR_NAME = "displayname";
/**
- * The XML name of the port attribute of a
- * SctpConnection of a conference IQ which represents
- * the SCTP port property of
- * ColibriConferenceIQ.SctpConnection.
+ * The name of the 'endpoint' element.
*/
- public static final String PORT_ATTR_NAME = "port";
+ public static final String ELEMENT_NAME = "endpoint";
/**
- * SCTP port attribute. 5000 by default.
+ * The name of the 'id' attribute.
*/
- private int port = 5000;
+ public static final String ID_ATTR_NAME = "id";
/**
- * Initializes a new SctpConnection instance without an
- * endpoint name and with default port value set.
+ * The 'display name' of this Endpoint.
*/
- public SctpConnection()
- {
- super(SctpConnection.ELEMENT_NAME);
- }
+ private String displayName;
/**
- * Gets the SCTP port of the SctpConnection described by this
- * instance.
- *
- * @return the SCTP port of the SctpConnection represented by
- * this instance.
+ * The 'id' of this Endpoint.
*/
- public int getPort()
+ private String id;
+
+ /**
+ * Initializes a new Endpoint with the given ID and display
+ * name.
+ * @param id the ID.
+ * @param displayName the display name.
+ */
+ public Endpoint(String id, String displayName)
{
- return port;
+ this.id = id;
+ this.displayName = displayName;
}
/**
- * Sets the SCTP port of the SctpConnection represented by this
- * instance.
- *
- * @param port the SCTP port of the SctpConnection
- * represented by this instance
+ * Returns the display name of this Endpoint.
+ * @return the display name of this Endpoint.
*/
- public void setPort(int port)
+ public String getDisplayName()
{
- this.port = port;
+ return displayName;
}
/**
- * {@inheritDoc}
+ * Returns the ID of this Endpoint.
+ * @return the ID of this Endpoint.
*/
- @Override
- protected void printAttributes(StringBuilder xml)
+ public String getId()
{
- xml.append(' ').append(PORT_ATTR_NAME).append("='")
- .append(getPort()).append('\'');
+ return id;
}
/**
- * {@inheritDoc}
- *
- * No content other than transport for SctpConnection.
+ * Sets the display name of this Endpoint.
+ * @param displayName the display name to set.
*/
- @Override
- protected boolean hasContent()
+ public void setDisplayName(String displayName)
{
- return false;
+ this.displayName = displayName;
}
- @Override
- protected void printContent(StringBuilder xml)
+ /**
+ * Sets the ID of this Endpoint.
+ * @param id the ID to set.
+ */
+ public void setId(String id)
{
- // No other content than the transport shared from ChannelCommon
+ this.id = id;
}
}
@@ -1764,6 +1861,11 @@ public static class Recording
*/
public static final String ELEMENT_NAME = "recording";
+ /**
+ * The XML name of the path attribute.
+ */
+ public static final String PATH_ATTR_NAME = "path";
+
/**
* The XML name of the state attribute.
*/
@@ -1774,14 +1876,11 @@ public static class Recording
*/
public static final String TOKEN_ATTR_NAME = "token";
- /**
- * The XML name of the path attribute.
- */
- public static final String PATH_ATTR_NAME = "path";
+ private String path;
- private String token = null;
private boolean state;
- private String path = null;
+
+ private String token;
public Recording(boolean state)
{
@@ -1795,24 +1894,24 @@ public Recording(boolean state, String token)
this.token = token;
}
- public String getToken()
+ public String getPath()
{
- return token;
+ return path;
}
- public String getPath()
+ public boolean getState()
{
- return path;
+ return state;
}
- public void setPath(String path)
+ public String getToken()
{
- this.path = path;
+ return token;
}
- public boolean getState()
+ public void setPath(String path)
{
- return state;
+ this.path = path;
}
public void toXML(StringBuilder xml)
@@ -1834,82 +1933,119 @@ public void toXML(StringBuilder xml)
}
}
+ public static class RTCPTerminationStrategy
+ {
+ public static final String ELEMENT_NAME = "rtcp-termination-strategy";
+
+ public static final String NAME_ATTR_NAME = "name";
+
+ private String name;
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ public void toXML(StringBuilder xml)
+ {
+ xml.append('<').append(ELEMENT_NAME);
+ xml.append(' ').append(NAME_ATTR_NAME).append("='")
+ .append(name).append('\'');
+ xml.append("/>");
+ }
+ }
+
/**
- * Represents an 'endpoint' element.
+ * Represents a SCTP connection included into a content
+ * of a Jitsi Videobridge conference IQ.
+ *
+ * @author Pawel Domas
*/
- public static class Endpoint
+ public static class SctpConnection
+ extends ChannelCommon
{
/**
- * The name of the 'endpoint' element.
- */
- public static final String ELEMENT_NAME = "endpoint";
-
- /**
- * The name of the 'id' attribute.
+ * The XML element name of a content of a Jitsi Videobridge
+ * conference IQ.
*/
- public static final String ID_ATTR_NAME = "id";
+ public static final String ELEMENT_NAME = "sctpconnection";
/**
- * The name of the 'displayname' attribute.
+ * The XML name of the port attribute of a
+ * SctpConnection of a conference IQ which represents
+ * the SCTP port property of
+ * ColibriConferenceIQ.SctpConnection.
*/
- public static final String DISPLAYNAME_ATTR_NAME = "displayname";
+ public static final String PORT_ATTR_NAME = "port";
/**
- * The 'id' of this Endpoint.
+ * SCTP port attribute. 5000 by default.
*/
- private String id;
+ private int port = 5000;
/**
- * The 'display name' of this Endpoint.
+ * Initializes a new SctpConnection instance without an
+ * endpoint name and with default port value set.
*/
- private String displayName;
+ public SctpConnection()
+ {
+ super(SctpConnection.ELEMENT_NAME);
+ }
/**
- * Initializes a new Endpoint with the given ID and display
- * name.
- * @param id the ID.
- * @param displayName the display name.
+ * Gets the SCTP port of the SctpConnection described by this
+ * instance.
+ *
+ * @return the SCTP port of the SctpConnection represented by
+ * this instance.
*/
- public Endpoint(String id, String displayName)
+ public int getPort()
{
- this.id = id;
- this.displayName = displayName;
+ return port;
}
/**
- * Sets the ID of this Endpoint.
- * @param id the ID to set.
+ * {@inheritDoc}
+ *
+ * No content other than transport for SctpConnection.
*/
- public void setId(String id)
+ @Override
+ protected boolean hasContent()
{
- this.id = id;
+ return false;
}
/**
- * Returns the ID of this Endpoint.
- * @return the ID of this Endpoint.
+ * {@inheritDoc}
*/
- public String getId()
+ @Override
+ protected void printAttributes(StringBuilder xml)
{
- return id;
+ xml.append(' ').append(PORT_ATTR_NAME).append("='")
+ .append(getPort()).append('\'');
}
- /**
- * Sets the display name of this Endpoint.
- * @param displayName the display name to set.
- */
- public void setDisplayName(String displayName)
+ @Override
+ protected void printContent(StringBuilder xml)
{
- this.displayName = displayName;
+ // No other content than the transport shared from ChannelCommon
}
/**
- * Returns the display name of this Endpoint.
- * @return the display name of this Endpoint.
+ * Sets the SCTP port of the SctpConnection represented by this
+ * instance.
+ *
+ * @param port the SCTP port of the SctpConnection
+ * represented by this instance
*/
- public String getDisplayName()
+ public void setPort(int port)
{
- return displayName;
+ this.port = port;
}
}
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java
index 8ce696733..0e2acebfb 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java
@@ -40,6 +40,11 @@ public ColibriIQProvider()
SourcePacketExtension.NAMESPACE,
new DefaultPacketExtensionProvider(
SourcePacketExtension.class));
+ providerManager.addExtensionProvider(
+ SourceGroupPacketExtension.ELEMENT_NAME,
+ SourceGroupPacketExtension.NAMESPACE,
+ new DefaultPacketExtensionProvider(
+ SourceGroupPacketExtension.class));
PacketExtensionProvider parameterProvider
= new DefaultPacketExtensionProvider(
@@ -84,6 +89,13 @@ else if (childExtension instanceof IceUdpTransportPacketExtension)
channel.setTransport(transport);
}
+ else if (childExtension instanceof SourceGroupPacketExtension)
+ {
+ SourceGroupPacketExtension sourceGroup
+ = (SourceGroupPacketExtension)childExtension;
+
+ channel.addSourceGroup(sourceGroup);
+ }
}
private void addChildExtension(
@@ -187,7 +199,9 @@ else if (ColibriConferenceIQ.Channel.ELEMENT_NAME.equals(
else if (ColibriConferenceIQ.SctpConnection.ELEMENT_NAME
.equals(name))
{
- content.addSctpConnection(sctpConnection);
+ if (sctpConnection != null)
+ content.addSctpConnection(sctpConnection);
+
sctpConnection = null;
}
else if (ColibriConferenceIQ.Endpoint.ELEMENT_NAME
@@ -327,6 +341,18 @@ else if (ColibriConferenceIQ.Recording.ELEMENT_NAME.equals(
if ((lastN != null) && (lastN.length() != 0))
channel.setLastN(Integer.parseInt(lastN));
+ // receiving simulcast layer
+ String receivingSimulcastLayer
+ = parser.getAttributeValue(
+ "",
+ ColibriConferenceIQ.Channel
+ .RECEIVING_SIMULCAST_LAYER);
+
+ if ((receivingSimulcastLayer != null)
+ && (receivingSimulcastLayer.length() != 0))
+ channel.setReceivingSimulcastLayer(
+ Integer.parseInt(receivingSimulcastLayer));
+
// rtcpPort
String rtcpPort
= parser.getAttributeValue(
@@ -426,20 +452,28 @@ else if (ColibriConferenceIQ.SctpConnection.ELEMENT_NAME
ColibriConferenceIQ.
SctpConnection.ENDPOINT_ATTR_NAME);
- if(!StringUtils.isNullOrEmpty(endpoint))
- {
- sctpConnection
- = new ColibriConferenceIQ.SctpConnection();
- }
- else
+ // id
+ String connID
+ = parser.getAttributeValue(
+ "",
+ ColibriConferenceIQ.
+ ChannelCommon.ID_ATTR_NAME);
+
+ if(StringUtils.isNullOrEmpty(connID)
+ && StringUtils.isNullOrEmpty(endpoint))
{
- throw new RuntimeException(
- "Endpoint is mandatory attribute"
- + " for SCTP connection"
- );
+ sctpConnection = null;
+ continue;
}
- sctpConnection.setEndpoint(endpoint);
+ sctpConnection
+ = new ColibriConferenceIQ.SctpConnection();
+
+ if (!StringUtils.isNullOrEmpty(connID))
+ sctpConnection.setID(connID);
+
+ if (!StringUtils.isNullOrEmpty(endpoint))
+ sctpConnection.setEndpoint(endpoint);
// port
String port
@@ -538,7 +572,14 @@ else if (SourcePacketExtension.ELEMENT_NAME.equals(name)
peName = name;
peNamespace = SourcePacketExtension.NAMESPACE;
}
-
+ else if (SourceGroupPacketExtension.ELEMENT_NAME
+ .equals(name)
+ && SourceGroupPacketExtension.NAMESPACE
+ .equals(parser.getNamespace()))
+ {
+ peName = name;
+ peNamespace = SourceGroupPacketExtension.NAMESPACE;
+ }
if (peName == null)
{
throwAway(parser, name);
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQProvider.java
index bc46b8f3e..a0d4e45f7 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQProvider.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQProvider.java
@@ -157,6 +157,13 @@ public JingleIQProvider()
new DefaultPacketExtensionProvider(
CallIdPacketExtension.class));
+ //rtcp-fb
+ providerManager.addExtensionProvider(
+ RtcpFbPacketExtension.ELEMENT_NAME,
+ RtcpFbPacketExtension.NAMESPACE,
+ new DefaultPacketExtensionProvider(
+ RtcpFbPacketExtension.class));
+
//rtcp-mux
providerManager.addExtensionProvider(
RtcpmuxPacketExtension.ELEMENT_NAME,
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/PayloadTypePacketExtension.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/PayloadTypePacketExtension.java
index 1dbcceb20..03746672a 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/PayloadTypePacketExtension.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/PayloadTypePacketExtension.java
@@ -217,4 +217,27 @@ public List getParameters()
{
return getChildExtensionsOfType(ParameterPacketExtension.class);
}
+
+ /**
+ * Adds an RTCP feedback type to the list that we already have registered
+ * for this payload type.
+ *
+ * @param rtcpFbPacketExtension RTCP feedback type for this encoding.
+ */
+ public void addRtcpFeedbackType(RtcpFbPacketExtension rtcpFbPacketExtension)
+ {
+ addChildExtension(rtcpFbPacketExtension);
+ }
+
+ /**
+ * Returns the list of RTCP feedback types currently registered for this
+ * payload type.
+ *
+ * @return the list of RTCP feedback types currently registered for this
+ * payload type.
+ */
+ public List getRtcpFeedbackTypeList()
+ {
+ return getChildExtensionsOfType(RtcpFbPacketExtension.class);
+ }
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/RtcpFbPacketExtension.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/RtcpFbPacketExtension.java
new file mode 100644
index 000000000..c807f055a
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/RtcpFbPacketExtension.java
@@ -0,0 +1,89 @@
+/*
+ * Jitsi, 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.jabber.extensions.jingle;
+
+import net.java.sip.communicator.impl.protocol.jabber.extensions.*;
+
+/**
+ * Packet extension that holds RTCP feedback types of the
+ * {@link PayloadTypePacketExtension}. Defined in XEP-0293.
+ *
+ * @author Pawel Domas
+ */
+public class RtcpFbPacketExtension
+ extends AbstractPacketExtension
+{
+ /**
+ * The name space for RTP feedback elements.
+ */
+ public static final String NAMESPACE = "urn:xmpp:jingle:apps:rtp:rtcp-fb:0";
+
+ /**
+ * The name of the RTCP feedback element.
+ */
+ public static final String ELEMENT_NAME = "rtcp-fb";
+
+ /**
+ * The name the attribute that holds the feedback type.
+ */
+ public static final String TYPE_ATTR_NAME = "type";
+
+ /**
+ * The name the attribute that holds the feedback subtype.
+ */
+ public static final String SUBTYPE_ATTR_NAME = "subtype";
+
+ /**
+ * Creates new empty instance of RtcpFbPacketExtension.
+ */
+ public RtcpFbPacketExtension()
+ {
+ super(NAMESPACE, ELEMENT_NAME);
+ }
+
+ /**
+ * Sets RTCP feedback type attribute.
+ * @param feedbackType the RTCP feedback type to set.
+ */
+ public void setFeedbackType(String feedbackType)
+ {
+ setAttribute(TYPE_ATTR_NAME, feedbackType);
+ }
+
+ /**
+ * Returns RTCP feedback type attribute value if already set
+ * or null otherwise.
+ *
+ * @return RTCP feedback type attribute if already set or null
+ * otherwise.
+ */
+ public String getFeedbackType()
+ {
+ return getAttributeAsString(TYPE_ATTR_NAME);
+ }
+
+ /**
+ * Sets RTCP feedback subtype attribute.
+ * @param feedbackSubType the RTCP feedback subtype to set.
+ */
+ public void setFeedbackSubtype(String feedbackSubType)
+ {
+ setAttribute(SUBTYPE_ATTR_NAME, feedbackSubType);
+ }
+
+ /**
+ * Returns RTCP feedback subtype attribute value if already set
+ * or null otherwise.
+ *
+ * @return RTCP feedback subtype attribute if already set or null
+ * otherwise.
+ */
+ public String getFeedbackSubtype()
+ {
+ return getAttributeAsString(SUBTYPE_ATTR_NAME);
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/SourceGroupPacketExtension.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/SourceGroupPacketExtension.java
new file mode 100644
index 000000000..9b540025a
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/SourceGroupPacketExtension.java
@@ -0,0 +1,89 @@
+/*
+ * Jitsi, 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.jabber.extensions.jingle;
+
+import net.java.sip.communicator.impl.protocol.jabber.extensions.*;
+import net.java.sip.communicator.impl.protocol.jabber.extensions.colibri.*;
+
+import java.util.*;
+
+/**
+ * Represents ssrc-group elements described in XEP-0339.
+ *
+ * Created by gp on 07/08/14.
+ */
+public class SourceGroupPacketExtension
+ extends AbstractPacketExtension
+{
+
+ /**
+ * The name of the "ssrc-group" element.
+ */
+ public static final String ELEMENT_NAME = "ssrc-group";
+
+ /**
+ * The namespace for the "ssrc-group" element.
+ */
+ public static final String NAMESPACE = "urn:xmpp:jingle:apps:rtp:ssma:0";
+
+ /**
+ * The name of the payload id SDP argument.
+ */
+ public static final String SEMANTICS_ATTR_NAME = "semantics";
+
+ /**
+ * Creates a new {@link SourceGroupPacketExtension} instance with the proper
+ * element name and namespace.
+ */
+ public SourceGroupPacketExtension()
+ {
+ super(NAMESPACE, ELEMENT_NAME);
+ }
+
+ /**
+ * Gets the semantics of this source group.
+ *
+ * @return the semantics of this source group.
+ */
+ public String getSemantics()
+ {
+ return getAttributeAsString(SEMANTICS_ATTR_NAME);
+ }
+
+ /**
+ * Sets the semantics of this source group.
+ */
+ public void setSemantics(String semantics)
+ {
+ this.setAttribute(SEMANTICS_ATTR_NAME, semantics);
+ }
+
+ /**
+ * Gets the sources of this source group.
+ *
+ * @return the sources of this source group.
+ */
+ public List getSources()
+ {
+ return getChildExtensionsOfType(SourcePacketExtension.class);
+ }
+
+ /**
+ * Sets the sources of this source group.
+ *
+ * @param sources the sources of this source group.
+ */
+ public void addSources(List sources)
+ {
+ if (sources != null && sources.size() != 0)
+ {
+ for (SourcePacketExtension source : sources)
+ this.addChildExtension(source);
+ }
+
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/UriHandlerSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/UriHandlerSipImpl.java
index 5aa1b0fbe..89feea774 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/UriHandlerSipImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/UriHandlerSipImpl.java
@@ -26,6 +26,20 @@
public class UriHandlerSipImpl
implements UriHandler, ServiceListener, AccountManagerListener
{
+ /**
+ * Property to set the amount of time to wait for SIP registration
+ * to complete before trying to dial a URI from the command line.
+ * (value in milliseconds).
+ */
+ public static final String INITIAL_REGISTRATION_TIMEOUT_PROP
+ = "net.java.sip.communicator.impl.protocol.sip.call.INITIAL_REGISTRATION_TIMEOUT";
+
+ /**
+ * Default value for INITIAL_REGISTRATION_TIMEOUT (milliseconds)
+ */
+ public static final long DEFAULT_INITIAL_REGISTRATION_TIMEOUT
+ = 5000;
+
/**
* The Logger used by the UriHandlerSipImpl class and its
* instances for logging output.
@@ -254,12 +268,11 @@ public String getProtocol()
}
/**
- * Parses the specified URI and creates a call with the currently active
- * telephony operation set.
+ * Parses the specified URI and tries to create a call when online.
*
* @param uri the SIP URI that we have to call.
*/
- public void handleUri(String uri)
+ public void handleUri(final String uri)
{
/*
* TODO If the requirement to register the factory service after
@@ -278,7 +291,7 @@ public void handleUri(String uri)
}
}
- ProtocolProviderService provider;
+ final ProtocolProviderService provider;
try
{
provider = selectHandlingProvider(uri);
@@ -301,6 +314,73 @@ public void handleUri(String uri)
return;
}
+ if(provider.getRegistrationState() == RegistrationState.REGISTERED)
+ {
+ handleUri(uri, provider);
+ }
+ else
+ {
+ // Allow a grace period for the provider to register in case
+ // we have just started up
+ long initialRegistrationTimeout =
+ SipActivator.getConfigurationService()
+ .getLong(INITIAL_REGISTRATION_TIMEOUT_PROP,
+ DEFAULT_INITIAL_REGISTRATION_TIMEOUT);
+ final DelayRegistrationStateChangeListener listener =
+ new DelayRegistrationStateChangeListener(uri, provider);
+ provider.addRegistrationStateChangeListener(listener);
+ new Timer().schedule(new TimerTask()
+ {
+ @Override
+ public void run()
+ {
+ provider.removeRegistrationStateChangeListener(listener);
+ // Even if not registered after the timeout, try the call
+ // anyway and the error popup will appear to ask the
+ // user if they want to register
+ handleUri(uri, provider);
+ }
+ }, initialRegistrationTimeout);
+ }
+ }
+
+ /**
+ * Listener on provider state changes that handles the passed URI if the
+ * provider becomes registered.
+ */
+ private class DelayRegistrationStateChangeListener
+ implements RegistrationStateChangeListener
+ {
+ private String uri;
+ private ProtocolProviderService provider;
+ private boolean handled = false;
+
+ public DelayRegistrationStateChangeListener(String uri,
+ ProtocolProviderService provider)
+ {
+ this.uri = uri;
+ this.provider = provider;
+ }
+
+ @Override
+ public void registrationStateChanged(RegistrationStateChangeEvent evt)
+ {
+ if (evt.getNewState() == RegistrationState.REGISTERED && !handled)
+ {
+ provider.removeRegistrationStateChangeListener(this);
+ handled = true;
+ handleUri(uri, provider);
+ }
+ }
+ }
+
+ /**
+ * Creates a call with the currently active telephony operation set.
+ *
+ * @param uri the SIP URI that we have to call.
+ */
+ protected void handleUri(String uri, ProtocolProviderService provider)
+ {
//handle "sip://" URIs as "sip:"
if(uri != null)
uri = uri.replace("sip://", "sip:");
diff --git a/src/net/java/sip/communicator/service/muc/MUCService.java b/src/net/java/sip/communicator/service/muc/MUCService.java
index 8b5b9dae0..1fb75bf0f 100644
--- a/src/net/java/sip/communicator/service/muc/MUCService.java
+++ b/src/net/java/sip/communicator/service/muc/MUCService.java
@@ -26,6 +26,11 @@ public abstract class MUCService
public static final String DISABLED_PROPERTY
= "net.java.sip.communicator.impl.muc.MUC_SERVICE_DISABLED";
+ /**
+ * Key for auto-open configuration entry.
+ */
+ private static String AUTO_OPEN_CONFIG_KEY = "openAutomatically";
+
/**
* The value for chat room configuration property to open automatically on
* activity
@@ -44,6 +49,11 @@ public abstract class MUCService
*/
public static String OPEN_ON_IMPORTANT_MESSAGE = "on_important_message";
+ /**
+ * The default for chat room auto-open behaviour.
+ */
+ public static String DEFAULT_AUTO_OPEN_BEHAVIOUR = OPEN_ON_MESSAGE;
+
/**
* Map for the auto open configuration values and their text representation
*/
@@ -73,7 +83,7 @@ public static void setChatRoomAutoOpenOption(
{
ConfigurationUtils.updateChatRoomProperty(
pps,
- chatRoomId, "openAutomatically", value);
+ chatRoomId, AUTO_OPEN_CONFIG_KEY, value);
}
/**
@@ -88,7 +98,7 @@ public static String getChatRoomAutoOpenOption(
{
return ConfigurationUtils.getChatRoomProperty(
pps,
- chatRoomId, "openAutomatically");
+ chatRoomId, AUTO_OPEN_CONFIG_KEY);
}
/**