diff --git a/src/net/java/sip/communicator/impl/callhistory/CallHistoryServiceImpl.java b/src/net/java/sip/communicator/impl/callhistory/CallHistoryServiceImpl.java
index aed3ee75d..648f5f980 100644
--- a/src/net/java/sip/communicator/impl/callhistory/CallHistoryServiceImpl.java
+++ b/src/net/java/sip/communicator/impl/callhistory/CallHistoryServiceImpl.java
@@ -1077,7 +1077,7 @@ public int compare(Object o1, Object o2)
* Receive events for adding or removing participants from a call
*/
private class HistoryCallChangeListener
- implements CallChangeListener
+ extends CallChangeAdapter
{
public void callParticipantAdded(CallParticipantEvent evt)
{
@@ -1089,7 +1089,5 @@ public void callParticipantRemoved(CallParticipantEvent evt)
handleParticipantRemoved(evt.getSourceCallParticipant(),
evt.getSourceCall());
}
-
- public void callStateChanged(CallChangeEvent evt){}
}
}
diff --git a/src/net/java/sip/communicator/impl/media/CallSessionImpl.java b/src/net/java/sip/communicator/impl/media/CallSessionImpl.java
index de7b45ece..bbebc7a84 100644
--- a/src/net/java/sip/communicator/impl/media/CallSessionImpl.java
+++ b/src/net/java/sip/communicator/impl/media/CallSessionImpl.java
@@ -382,11 +382,19 @@ private void startStreaming()
* Stops and closes all streams that have been initialized for local
* RTP managers.
*/
- private void stopStreaming()
+ public void stopStreaming()
{
- stopStreaming(getAudioRtpManager(), "audio");
+ RTPManager audioRtpManager = getAudioRtpManager();
+ if (audioRtpManager != null)
+ {
+ stopStreaming(audioRtpManager, "audio");
+ }
this.audioRtpManager = null;
- stopStreaming(getVideoRtpManager(), "video");
+ RTPManager videoRtpManager = getAudioRtpManager();
+ if (videoRtpManager != null)
+ {
+ stopStreaming(videoRtpManager, "video");
+ }
this.videoRtpManager = null;
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ActiveCallsRepository.java b/src/net/java/sip/communicator/impl/protocol/jabber/ActiveCallsRepository.java
index 354a2c785..c09c95700 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/ActiveCallsRepository.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/ActiveCallsRepository.java
@@ -6,10 +6,11 @@
*/
package net.java.sip.communicator.impl.protocol.jabber;
-import net.java.sip.communicator.util.*;
import java.util.*;
-import net.java.sip.communicator.service.protocol.event.*;
+
import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.service.protocol.event.*;
+import net.java.sip.communicator.util.*;
import org.jivesoftware.smackx.jingle.*;
/**
@@ -21,7 +22,7 @@
* @author Symphorien Wanko
*/
public class ActiveCallsRepository
- implements CallChangeListener
+ extends CallChangeAdapter
{
/**
* logger of this class
@@ -60,22 +61,6 @@ public void addCall(CallJabberImpl call)
call.addCallChangeListener(this);
}
- /**
- * A dummy implementation of the CallChangeListener method that we don't
- * use.
- * @param evt unused.
- */
- public void callParticipantAdded(CallParticipantEvent evt)
- {}
-
- /**
- * A dummy implementation of the CallChangeListener method that we don't
- * use.
- * @param evt unused.
- */
- public void callParticipantRemoved(CallParticipantEvent evt)
- {}
-
/**
* If evt indicates that the call has been ended we remove it from
* the repository.
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/ActiveCallsRepository.java b/src/net/java/sip/communicator/impl/protocol/sip/ActiveCallsRepository.java
index 5e353dfdf..f96eef3a2 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/ActiveCallsRepository.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/ActiveCallsRepository.java
@@ -6,12 +6,13 @@
*/
package net.java.sip.communicator.impl.protocol.sip;
-import net.java.sip.communicator.util.*;
import java.util.*;
-import net.java.sip.communicator.service.protocol.event.*;
-import net.java.sip.communicator.service.protocol.*;
import javax.sip.*;
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.service.protocol.event.*;
+import net.java.sip.communicator.util.*;
+
/**
* Keeps a list of all calls currently active and maintained by this protocol
* povider. Offers methods for finding a call by its ID, participant dialog
@@ -20,7 +21,7 @@
* @author Emil Ivov
*/
public class ActiveCallsRepository
- implements CallChangeListener
+ extends CallChangeAdapter
{
private static final Logger logger
= Logger.getLogger(ActiveCallsRepository.class);
@@ -51,22 +52,6 @@ public void addCall(CallSipImpl call)
call.addCallChangeListener(this);
}
- /**
- * A dummy implementation of the CallChangeListener method that we don't
- * use.
- * @param evt unused.
- */
- public void callParticipantAdded(CallParticipantEvent evt)
- {}
-
- /**
- * A dummy implementation of the CallChangeListener method that we don't
- * use.
- * @param evt unused.
- */
- public void callParticipantRemoved(CallParticipantEvent evt)
- {}
-
/**
* If evt indicates that the call has been ended we remove it from
* the repository.
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/DialogUtils.java b/src/net/java/sip/communicator/impl/protocol/sip/DialogUtils.java
new file mode 100644
index 000000000..94aafc18d
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/sip/DialogUtils.java
@@ -0,0 +1,255 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.protocol.sip;
+
+import java.util.*;
+import javax.sip.*;
+
+/**
+ * Implements utility methods to aid the manipulation of {@link Dialog}
+ * instances and extend the mentioned type with additional functionality.
+ *
+ * @author Lubomir Marinov
+ */
+public final class DialogUtils
+{
+
+ /**
+ * Associates a specific subscription with the a given Dialog
+ * in order to allow it to keep the dialog in question alive even after a
+ * BYE request.
+ *
+ * @param dialog the Dialog to associate the subscription with
+ * and to be kept alive after a BYE request because of the
+ * subscription
+ * @param subscription the subscription to be associated with
+ * dialog and keep it alive after a BYE request
+ * @return true if the specified subscription was associated with
+ * the given dialog; false if no changes were applied
+ * @throws SipException
+ */
+ public static boolean addSubscription(Dialog dialog, Object subscription)
+ throws SipException
+ {
+ synchronized (dialog)
+ {
+ DialogApplicationData applicationData =
+ (DialogApplicationData) dialog.getApplicationData();
+ if (applicationData == null)
+ {
+ applicationData = new DialogApplicationData();
+ dialog.setApplicationData(applicationData);
+ }
+
+ if (applicationData.addSubscription(subscription))
+ {
+ try
+ {
+ dialog.terminateOnBye(false);
+ return true;
+ }
+ catch (SipException ex)
+ {
+
+ /*
+ * Since the subscription didn't quite register, undo the
+ * part of the registration which did succeed.
+ */
+ applicationData.removeSubscription(subscription);
+ throw ex;
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Processes a BYE request in a specific Dialog for the
+ * purposes of subscription associations and returns an indicator which
+ * determines whether the specified dialog should still be considered alive
+ * after the processing of the BYE request.
+ *
+ * @param dialog the Dialog in which a BYE request has arrived
+ * @return true if dialog should still be considered
+ * alive after processing the mentioned BYE request; false
+ * if dialog is to be expected to die after processing
+ * the request in question
+ * @throws SipException
+ */
+ public static boolean processByeThenIsDialogAlive(Dialog dialog)
+ throws SipException
+ {
+ synchronized (dialog)
+ {
+ DialogApplicationData applicationData =
+ (DialogApplicationData) dialog.getApplicationData();
+ if (applicationData != null)
+ {
+ applicationData.setByeProcessed(true);
+
+ if (applicationData.getSubscriptionCount() > 0)
+ {
+ dialog.terminateOnBye(false);
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Dissociates a specific subscription with a given Dialog in
+ * order to no longer allow it to keep the dialog in question alive even
+ * after a BYE request, deletes the dialog if there are no other
+ * subscriptions associated with it and a BYE request has already been
+ * received and returns an indicator which determines whether the specified
+ * dialog is still alive after the dissociation of the given subscription.
+ *
+ * @param dialog the Dialog to dissociate the subscription with
+ * and to no longer be kept alive after a BYE request because of
+ * the subscription
+ * @param subscription the subscription to be dissociated with
+ * dialog and to no longer be kept alive after a BYE
+ * request because of the subscription
+ * @return true if the dialog is still alive after the
+ * dissociation; false if the dialog was terminated because
+ * of the dissociation
+ */
+ public static boolean removeSubscriptionThenIsDialogAlive(Dialog dialog,
+ Object subscription)
+ {
+ synchronized (dialog)
+ {
+ DialogApplicationData applicationData =
+ (DialogApplicationData) dialog.getApplicationData();
+ if ((applicationData != null)
+ && applicationData.removeSubscription(subscription)
+ && (applicationData.getSubscriptionCount() <= 0)
+ && applicationData.isByeProcessed())
+ {
+ dialog.delete();
+ return false;
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Prevents the creation of DialogUtils instances.
+ */
+ private DialogUtils()
+ {
+ }
+
+ /**
+ * Represents the application-specific data which the SIP protocol provider
+ * associates with {@link #Dialog} instances.
+ *
+ * The implementation at the time of this writing allows tracking
+ * subscriptions in a specific Dialog in order to make it
+ * possible to determine whether a BYE request should terminate the
+ * respective dialog.
+ *
+ */
+ private static class DialogApplicationData
+ {
+
+ /**
+ * The indicator which determines whether a BYE request has already been
+ * processed in the owning Dialog and thus allows
+ * determining whether the dialog in question should be terminated when
+ * the last associated subscription is terminated.
+ */
+ private boolean byeIsProcessed;
+
+ /**
+ * The set of subscriptions not yet terminated in the owning
+ * Dialog i.e. keeping it alive even after a BYE request.
+ */
+ private final List