aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip/communicator
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/java/sip/communicator')
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/menus/AutoAnswerMenu.java22
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/CallGTalkImpl.java15
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/CallJabberImpl.java12
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/OperationSetAutoAnswerJabberImpl.java175
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java20
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java2
-rw-r--r--src/net/java/sip/communicator/impl/protocol/sip/OperationSetAutoAnswerSipImpl.java264
-rw-r--r--src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java20
-rw-r--r--src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java5
-rw-r--r--src/net/java/sip/communicator/service/protocol/AbstractOperationSetBasicAutoAnswer.java298
-rw-r--r--src/net/java/sip/communicator/service/protocol/OperationSetBasicAutoAnswer.java23
11 files changed, 543 insertions, 313 deletions
diff --git a/src/net/java/sip/communicator/impl/gui/main/menus/AutoAnswerMenu.java b/src/net/java/sip/communicator/impl/gui/main/menus/AutoAnswerMenu.java
index 371bf4a..2d9563c 100644
--- a/src/net/java/sip/communicator/impl/gui/main/menus/AutoAnswerMenu.java
+++ b/src/net/java/sip/communicator/impl/gui/main/menus/AutoAnswerMenu.java
@@ -328,6 +328,11 @@ public class AutoAnswerMenu
private JRadioButton customValueRadio;
/**
+ * Check box to active the video answer for wideo calls.
+ */
+ private SIPCommCheckBox answerWithVideoCheckBox;
+
+ /**
* Custom field name text field.
*/
private JTextField headerNameField = new JTextField();
@@ -469,6 +474,17 @@ public class AutoAnswerMenu
c.insets = new Insets(10, 0, 0, 0);
}
+ c.gridy = currentRow++;
+ mainPanel.add(
+ getTitlePanel(
+ R.getI18NString("service.gui.AUTO_ANSWER_VIDEO")),
+ c);
+ c.gridy = currentRow++;
+ answerWithVideoCheckBox = new SIPCommCheckBox(
+ R.getI18NString(
+ "service.gui.AUTO_ANSWER_VIDEO_CALLS_WITH_VIDEO"));
+ mainPanel.add(answerWithVideoCheckBox, c);
+
TransparentPanel buttonsPanel
= new TransparentPanel(new FlowLayout(FlowLayout.RIGHT));
@@ -580,6 +596,9 @@ public class AutoAnswerMenu
opSetAdvanced.setCallForward(
callFwdNumberField.getText());
}
+
+ opset.setAutoAnswerWithVideo(
+ answerWithVideoCheckBox.isSelected());
}
dispose();
@@ -641,6 +660,9 @@ public class AutoAnswerMenu
callFwdNumberField.setText(opSetAdvanced.getCallForward());
}
}
+
+ answerWithVideoCheckBox.setSelected(
+ opset.isAutoAnswerWithVideoSet());
}
}
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/CallGTalkImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/CallGTalkImpl.java
index abc7eeb..c067c51 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/CallGTalkImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/CallGTalkImpl.java
@@ -162,6 +162,21 @@ public class CallGTalkImpl
if(this.getCallPeerCount() == 1 && this.getCallGroup() == null)
parentOpSet.fireCallEvent( CallEvent.CALL_RECEIVED, this);
+ // Manages auto answer with "audio only", or "audio / video" answer.
+ OperationSetAutoAnswerJabberImpl autoAnswerOpSet
+ = (OperationSetAutoAnswerJabberImpl)
+ this.getProtocolProvider()
+ .getOperationSet(OperationSetBasicAutoAnswer.class);
+
+ if(autoAnswerOpSet != null)
+ {
+ // With Gtalk, we do not actually supports the detection if the
+ // incoming call is a video call (cf. the fireCallEvent above with
+ // only 2 arguments). Thus, we set the auto-answer video
+ // parameter to false.
+ autoAnswerOpSet.autoAnswer(this, false);
+ }
+
return callPeer;
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/CallJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/CallJabberImpl.java
index 6b81c16..44d43a2 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/CallJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/CallJabberImpl.java
@@ -303,6 +303,18 @@ public class CallJabberImpl
parentOpSet.fireCallEvent(CallEvent.CALL_RECEIVED, this,
directions);
+ // Manages auto answer with "audio only", or "audio / video" answer.
+ OperationSetAutoAnswerJabberImpl autoAnswerOpSet
+ = (OperationSetAutoAnswerJabberImpl)
+ this.getProtocolProvider()
+ .getOperationSet(OperationSetBasicAutoAnswer.class);
+
+ if(autoAnswerOpSet != null)
+ {
+ autoAnswerOpSet.autoAnswer(this, directions);
+ }
+
+
return callPeer;
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetAutoAnswerJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetAutoAnswerJabberImpl.java
index af07efc..12343d1 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetAutoAnswerJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetAutoAnswerJabberImpl.java
@@ -6,6 +6,7 @@
*/
package net.java.sip.communicator.impl.protocol.jabber;
+import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
@@ -17,59 +18,29 @@ import java.util.*;
* calls.
*
* @author Damian Minkov
+ * @author Vincent Lucas
*/
public class OperationSetAutoAnswerJabberImpl
- extends CallPeerAdapter
- implements OperationSetBasicAutoAnswer
+ extends AbstractOperationSetBasicAutoAnswer
{
/**
- * Our class logger.
- */
- private static final Logger logger
- = Logger.getLogger(OperationSetAutoAnswerJabberImpl.class);
-
- /**
- * Should we unconditionally answer.
- */
- private boolean answerUnconditional = false;
-
- /**
- * The parent operation set.
- */
- private final OperationSetBasicTelephonyJabberImpl telephonyJabber;
-
- /**
* Creates this operation set, loads stored values, populating
* local variable settings.
*
- * @param telephonyJabber the parent opset.
- */
- OperationSetAutoAnswerJabberImpl(
- OperationSetBasicTelephonyJabberImpl telephonyJabber)
- {
- this.telephonyJabber = telephonyJabber;
-
- // init values from account props
- load();
- }
-
- /**
- * Load values from account properties.
+ * @param protocolProvider the parent Protocol Provider.
*/
- private void load()
+ public OperationSetAutoAnswerJabberImpl(
+ ProtocolProviderServiceJabberImpl protocolProvider)
{
- AccountID acc = telephonyJabber.getProtocolProvider().getAccountID();
-
- answerUnconditional
- = acc.getAccountPropertyBoolean(AUTO_ANSWER_UNCOND_PROP, false);
+ super(protocolProvider);
}
/**
* Saves values to account properties.
*/
- private void save()
+ protected void save()
{
- AccountID acc = telephonyJabber.getProtocolProvider().getAccountID();
+ AccountID acc = protocolProvider.getAccountID();
Map<String, String> accProps = acc.getAccountProperties();
// lets clear anything before saving :)
@@ -78,124 +49,50 @@ public class OperationSetAutoAnswerJabberImpl
if(answerUnconditional)
accProps.put(AUTO_ANSWER_UNCOND_PROP, Boolean.TRUE.toString());
+ accProps.put(AUTO_ANSWER_WITH_VIDEO_PROP,
+ Boolean.toString(this.answerWithVideo));
+
acc.setAccountProperties(accProps);
JabberActivator.getProtocolProviderFactory().storeAccount(acc);
}
/**
- * Sets the auto answer option to unconditionally answer all incoming calls.
- */
- public void setAutoAnswerUnconditional()
- {
- clearLocal();
-
- this.answerUnconditional = true;
-
- save();
- }
-
- /**
- * Is the auto answer option set to unconditionally
- * answer all incoming calls.
- * @return is auto answer set to unconditional.
- */
- public boolean isAutoAnswerUnconditionalSet()
- {
- return answerUnconditional;
- }
-
- /**
- * Clear local settings.
- */
- private void clearLocal()
- {
- this.answerUnconditional = false;
- }
-
- /**
- * Clear any previous settings.
+ * Checks if the call satisfy the auto answer conditions.
+ *
+ * @param call The new incoming call to auto-answer if needed.
+ *
+ * @return <tt>true</tt> if the call satisfy the auto answer conditions.
+ * <tt>False</tt> otherwise.
*/
- public void clear()
+ protected boolean satisfyAutoAnswerConditions(Call call)
{
- clearLocal();
-
- save();
+ // Nothing to do here, as long as the jabber account does not implements
+ // advanced auto answer functionnalities.
+ return false;
}
/**
- * Makes a check after creating call locally, should we answer it.
- * @param call the created call to answer if needed.
+ * Auto-answers to a call with "audio only" or "audio/video" if the incoming
+ * call is a video call.
+ *
+ * @param call The new incoming call to auto-answer if needed.
+ * @param directions The media type (audio / video) stream directions.
+ *
* @return <tt>true</tt> if we have processed and no further processing is
* needed, <tt>false</tt> otherwise.
*/
- boolean followCallCheck(AbstractCall<?, ?> call)
- {
- if(!answerUnconditional)
- return false;
-
- // We are here because we satisfy the conditional, or unconditional is
- // true.
- Iterator<? extends CallPeer> peers = call.getCallPeers();
-
- while (peers.hasNext())
- answerPeer(peers.next());
-
- return true;
- }
-
- /**
- * Answers call if peer in correct state or wait for it.
- * @param peer the peer to check and answer.
- */
- private void answerPeer(final CallPeer peer)
+ public boolean autoAnswer(
+ Call call,
+ Map<MediaType, MediaDirection> directions)
{
- CallPeerState state = peer.getState();
+ boolean isVideoCall = false;
+ MediaDirection direction = directions.get(MediaType.VIDEO);
- if (state == CallPeerState.INCOMING_CALL)
- {
- // answer in separate thread, don't block current processing
- new Thread(new Runnable()
- {
- public void run()
- {
- try
- {
- telephonyJabber.answerCallPeer(peer);
- }
- catch (OperationFailedException e)
- {
- logger.error("Could not answer to : " + peer
- + " caused by the following exception: " + e);
- }
- }
- }, getClass().getName()).start();
- }
- else
+ if(direction != null)
{
- peer.addCallPeerListener(this);
+ isVideoCall = (direction == MediaDirection.SENDRECV);
}
- }
- /**
- * If we peer was not in proper state wait for it and then answer.
- * @param evt the <tt>CallPeerChangeEvent</tt> instance containing the
- */
- public void peerStateChanged(CallPeerChangeEvent evt)
- {
- CallPeerState newState = (CallPeerState) evt.getNewValue();
-
- if (newState == CallPeerState.INCOMING_CALL)
- {
- CallPeer peer = evt.getSourceCallPeer();
-
- peer.removeCallPeerListener(this);
-
- answerPeer(peer);
- }
- else if (newState == CallPeerState.DISCONNECTED
- || newState == CallPeerState.FAILED)
- {
- evt.getSourceCallPeer().removeCallPeerListener(this);
- }
+ return super.autoAnswer(call, isVideoCall);
}
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java
index 731b892..c012e7a 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java
@@ -1042,16 +1042,6 @@ public class OperationSetBasicTelephonyJabberImpl
public void run()
{
callThread.processSessionInitiate(jingleIQ);
-
- OperationSetAutoAnswerJabberImpl autoAnswerOpSet =
- (OperationSetAutoAnswerJabberImpl)protocolProvider
- .getOperationSet(OperationSetBasicAutoAnswer.class);
-
- if(autoAnswerOpSet != null
- && autoAnswerOpSet.isAutoAnswerUnconditionalSet())
- {
- autoAnswerOpSet.followCallCheck(callThread);
- }
}
}.start();
@@ -1245,16 +1235,6 @@ public class OperationSetBasicTelephonyJabberImpl
CallGTalkImpl call = new CallGTalkImpl(this);
call.processGTalkInitiate(sessionIQ);
- OperationSetAutoAnswerJabberImpl autoAnswerOpSet =
- (OperationSetAutoAnswerJabberImpl)protocolProvider
- .getOperationSet(OperationSetBasicAutoAnswer.class);
-
- if(autoAnswerOpSet != null
- && autoAnswerOpSet.isAutoAnswerUnconditionalSet())
- {
- autoAnswerOpSet.followCallCheck(call);
- }
-
return;
}
else if (callPeer == null)
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java
index e9e133d..ecdf983 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java
@@ -1697,7 +1697,7 @@ public class ProtocolProviderServiceJabberImpl
addSupportedOperationSet(
OperationSetBasicAutoAnswer.class,
- new OperationSetAutoAnswerJabberImpl(basicTelephony));
+ new OperationSetAutoAnswerJabberImpl(this));
// init DTMF
OperationSetDTMFJabberImpl operationSetDTMFSip
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetAutoAnswerSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetAutoAnswerSipImpl.java
index a8bc35f..8883317 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetAutoAnswerSipImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetAutoAnswerSipImpl.java
@@ -7,14 +7,17 @@
package net.java.sip.communicator.impl.protocol.sip;
import gov.nist.javax.sip.header.*;
+import net.java.sip.communicator.impl.protocol.sip.sdp.*;
+import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
import javax.sip.*;
import javax.sip.address.*;
-import javax.sip.header.*;
+import javax.sip.header.ContactHeader; // Disambiguation.
import javax.sip.message.*;
+import javax.sdp.*;
import java.util.*;
/**
@@ -24,11 +27,11 @@ import java.util.*;
* on existence of specified header name and value.
*
* @author Damian Minkov
+ * @author Vincent Lucas
*/
public class OperationSetAutoAnswerSipImpl
- extends CallPeerAdapter
- implements OperationSetBasicAutoAnswer,
- OperationSetAdvancedAutoAnswer
+ extends AbstractOperationSetBasicAutoAnswer
+ implements OperationSetAdvancedAutoAnswer
{
/**
* Our class logger.
@@ -37,16 +40,6 @@ public class OperationSetAutoAnswerSipImpl
Logger.getLogger(OperationSetBasicTelephonySipImpl.class);
/**
- * The parent operation set.
- */
- private OperationSetBasicTelephonySipImpl telephonySip;
-
- /**
- * Should we unconditionally answer.
- */
- private boolean answerUnconditional = false;
-
- /**
* Should we answer on existence of some header and/or name.
*/
private boolean answerConditional = false;
@@ -70,26 +63,22 @@ public class OperationSetAutoAnswerSipImpl
* Creates this operation set, loads stored values, populating
* local variable settings.
*
- * @param telephonySip the parent opset.
+ * @param protocolProvider the parent Protocol Provider.
*/
- OperationSetAutoAnswerSipImpl(
- OperationSetBasicTelephonySipImpl telephonySip)
+ public OperationSetAutoAnswerSipImpl(
+ ProtocolProviderServiceSipImpl protocolProvider)
{
- this.telephonySip = telephonySip;
-
- // init values from account props
- load();
+ super(protocolProvider);
}
/**
* Load values from account properties.
*/
- private void load()
+ protected void load()
{
- AccountID acc = telephonySip.getProtocolProvider().getAccountID();
+ super.load();
- answerUnconditional =
- acc.getAccountPropertyBoolean(AUTO_ANSWER_UNCOND_PROP, false);
+ AccountID acc = protocolProvider.getAccountID();
headerName =
acc.getAccountPropertyString(AUTO_ANSWER_COND_NAME_PROP);
@@ -105,9 +94,9 @@ public class OperationSetAutoAnswerSipImpl
/**
* Saves values to account properties.
*/
- private void save()
+ protected void save()
{
- AccountID acc = telephonySip.getProtocolProvider().getAccountID();
+ AccountID acc = protocolProvider.getAccountID();
Map<String, String> accProps = acc.getAccountProperties();
// lets clear anything before saving :)
@@ -131,38 +120,20 @@ public class OperationSetAutoAnswerSipImpl
{
accProps.put(AUTO_ANSWER_FWD_NUM_PROP, callFwdTo);
}
+ accProps.put(
+ AUTO_ANSWER_WITH_VIDEO_PROP,
+ Boolean.toString(answerWithVideo));
acc.setAccountProperties(accProps);
SipActivator.getProtocolProviderFactory().storeAccount(acc);
}
/**
- * Sets the auto answer option to unconditionally answer all incoming calls.
- */
- public void setAutoAnswerUnconditional()
- {
- clearLocal();
-
- this.answerUnconditional = true;
-
- save();
- }
-
- /**
- * Is the auto answer option set to unconditionally
- * answer all incoming calls.
- * @return is auto answer set to unconditional.
- */
- public boolean isAutoAnswerUnconditionalSet()
- {
- return answerUnconditional;
- }
-
- /**
* Sets a specified header and its value if they exist in the incoming
* call packet this will activate auto answer.
* If value is empty or null it will be considered as any (will search
* only for a header with that name and ignore the value)
+ *
* @param headerName the name of the header to search
* @param value the value for the header, can be null.
*/
@@ -180,6 +151,7 @@ public class OperationSetAutoAnswerSipImpl
/**
* Is the auto answer option set to conditionally
* answer all incoming calls.
+ *
* @return is auto answer set to conditional.
*/
public boolean isAutoAnswerConditionSet()
@@ -190,6 +162,7 @@ public class OperationSetAutoAnswerSipImpl
/**
* Set to automatically forward all calls to the specified
* number using the same provider.
+ *
* @param numberTo number to use for forwarding
*/
public void setCallForward(String numberTo)
@@ -203,7 +176,8 @@ public class OperationSetAutoAnswerSipImpl
/**
* Get the value for automatically forward all calls to the specified
- * number using the same provider..
+ * number using the same provider.
+ *
* @return numberTo number to use for forwarding
*/
public String getCallForward()
@@ -214,9 +188,10 @@ public class OperationSetAutoAnswerSipImpl
/**
* Clear local settings.
*/
- private void clearLocal()
+ protected void clearLocal()
{
- this.answerUnconditional = false;
+ super.clearLocal();
+
this.answerConditional = false;
this.headerName = null;
this.headerValue = null;
@@ -224,17 +199,8 @@ public class OperationSetAutoAnswerSipImpl
}
/**
- * Clear any previous settings.
- */
- public void clear()
- {
- clearLocal();
-
- save();
- }
-
- /**
* Returns the name of the header if conditional auto answer is set.
+ *
* @return the name of the header if conditional auto answer is set.
*/
public String getAutoAnswerHeaderName()
@@ -244,6 +210,7 @@ public class OperationSetAutoAnswerSipImpl
/**
* Returns the value of the header for the conditional auto answer.
+ *
* @return the value of the header for the conditional auto answer.
*/
public String getAutoAnswerHeaderValue()
@@ -253,13 +220,16 @@ public class OperationSetAutoAnswerSipImpl
/**
* Makes a check before locally creating call, should we just forward it.
+ *
* @param invite the current invite to check.
* @param serverTransaction the transaction.
+ *
* @return <tt>true</tt> if we have processed and no further processing is
* needed, <tt>false</tt> otherwise.
*/
- boolean preCallCheck(Request invite,
- ServerTransaction serverTransaction)
+ public boolean forwardCall(
+ Request invite,
+ ServerTransaction serverTransaction)
{
if(StringUtils.isNullOrEmpty(callFwdTo))
return false;
@@ -270,13 +240,15 @@ public class OperationSetAutoAnswerSipImpl
if (logger.isTraceEnabled())
logger.trace("will send moved temporally response: ");
- response = telephonySip.getProtocolProvider().getMessageFactory()
+ response = ((ProtocolProviderServiceSipImpl) protocolProvider)
+ .getMessageFactory()
.createResponse(Response.MOVED_TEMPORARILY, invite);
ContactHeader contactHeader =
- (ContactHeader)response.getHeader(ContactHeader.NAME);
+ (ContactHeader)response.getHeader(ContactHeader.NAME);
AddressFactory addressFactory =
- telephonySip.getProtocolProvider().getAddressFactory();
+ ((ProtocolProviderServiceSipImpl) protocolProvider)
+ .getAddressFactory();
String destination = getCallForward();
if(!destination.startsWith("sip"))
@@ -300,105 +272,117 @@ public class OperationSetAutoAnswerSipImpl
}
/**
- * Makes a check after creating call locally, should we answer it.
- * @param invite the current invite to check.
- * @param call the created call to answer if needed.
- * @return <tt>true</tt> if we have processed and no further processing is
- * needed, <tt>false</tt> otherwise.
+ * Checks if the call satisfy the auto answer conditions.
+ *
+ * @param call The new incoming call to auto-answer if needed.
+ *
+ * @return <tt>true</tt> if the call satisfy the auto answer conditions.
+ * <tt>False</tt> otherwise.
*/
- boolean followCallCheck(Request invite,
- CallSipImpl call)
+ protected boolean satisfyAutoAnswerConditions(Call call)
{
- if(!(answerConditional || answerUnconditional))
- return false;
+ Iterator<? extends CallPeer> peers = call.getCallPeers();
+ CallPeer peer;
// lets check for headers
if(answerConditional)
{
- SIPHeader callAnswerHeader =
- (SIPHeader)invite.getHeader(headerName);
-
- if(callAnswerHeader == null)
- return false;
-
- if(!StringUtils.isNullOrEmpty(headerValue))
+ while(peers.hasNext())
{
- String value = callAnswerHeader.getHeaderValue();
+ peer = peers.next();
+ Transaction transaction = ((CallPeerSipImpl) peer)
+ .getLatestInviteTransaction();
+ if(transaction != null)
+ {
+ Request invite = transaction.getRequest();
+ SIPHeader callAnswerHeader = (SIPHeader)
+ invite.getHeader(headerName);
- if(value == null || !headerValue.equals(value))
- return false;
+ if(callAnswerHeader != null)
+ {
+ if(!StringUtils.isNullOrEmpty(headerValue))
+ {
+ String value = callAnswerHeader.getHeaderValue();
+
+ if(value != null && headerValue.equals(value))
+ {
+ return true;
+ }
+ }
+ }
+ }
}
}
+ return false;
+ }
- // we are here cause we satisfy the conditional,
- // or unconditional is true
- Iterator<? extends CallPeer> peers = call.getCallPeers();
-
- while (peers.hasNext())
+ /**
+ * Makes a check after creating call locally, should we answer it.
+ *
+ * @param call The new incoming call to auto-answer if needed.
+ * @param isVideoCall Indicates if the remote peer which has created this
+ * call wish to have a video call.
+ *
+ * @return <tt>true</tt> if we have processed and no further processing is
+ * needed, <tt>false</tt> otherwise.
+ */
+ public boolean autoAnswer(Call call)
+ {
+ if(answerUnconditional || satisfyAutoAnswerConditions(call))
{
- final CallPeer peer = peers.next();
-
- answerPeer(peer);
+ boolean isVideoCall = doesRequestContainsActiveVideoMediaType(call);
+ this.answerCall(call, isVideoCall);
+ return true;
}
-
- return true;
+ return false;
}
/**
- * Answers call if peer in correct state or wait for it.
- * @param peer the peer to check and answer.
+ * Detects if the incoming call is a video call. Parses the SDP from the SIP
+ * request to determine if the video is active.
+ *
+ * @param call The new incoming call to auto-answer if needed.
+ *
+ * @return True if the incoming call is a video call. False, otherwise.
*/
- private void answerPeer(final CallPeer peer)
+ private boolean doesRequestContainsActiveVideoMediaType(Call call)
{
- CallPeerState state = peer.getState();
+ Iterator<? extends CallPeer> peers = call.getCallPeers();
- if (state == CallPeerState.INCOMING_CALL)
+ while(peers.hasNext())
{
- // answer in separate thread, don't block current
- // processing
- new Thread(new Runnable()
+ Transaction transaction = ((CallPeerSipImpl) peers.next())
+ .getLatestInviteTransaction();
+ if(transaction != null)
{
- public void run()
+ Request inviteReq = transaction.getRequest();
+
+ if(inviteReq != null && inviteReq.getRawContent() != null)
{
- try
+ String sdpStr = SdpUtils.getContentAsString(inviteReq);
+ SessionDescription sesDescr
+ = SdpUtils.parseSdpString(sdpStr);
+ List<MediaDescription> remoteDescriptions
+ = SdpUtils.extractMediaDescriptions(sesDescr);
+
+ for (MediaDescription mediaDescription :
+ remoteDescriptions)
{
- telephonySip.answerCallPeer(peer);
- }
- catch (OperationFailedException e)
- {
- logger.error("Could not answer to : " + peer
- + " caused by the following exception: " + e);
+ if(SdpUtils.getMediaType(mediaDescription)
+ == MediaType.VIDEO)
+ {
+ if(SdpUtils.getDirection(mediaDescription)
+ == MediaDirection.SENDRECV)
+ {
+ return true;
+ }
+
+ }
}
}
- }, getClass().getName()).start();
- }
- else
- {
- peer.addCallPeerListener(this);
+ }
}
- }
- /**
- * If we peer was not in proper state wait for it and then answer.
- * @param evt the <tt>CallPeerChangeEvent</tt> instance containing the
- */
- public void peerStateChanged(CallPeerChangeEvent evt)
- {
-
- CallPeerState newState = (CallPeerState) evt.getNewValue();
-
- if (newState == CallPeerState.INCOMING_CALL)
- {
- CallPeer peer = evt.getSourceCallPeer();
-
- peer.removeCallPeerListener(this);
-
- answerPeer(peer);
- }
- else if (newState == CallPeerState.DISCONNECTED
- || newState == CallPeerState.FAILED)
- {
- evt.getSourceCallPeer().removeCallPeerListener(this);
- }
+ return false;
}
}
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java
index 839f7f1..d1eb25e 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java
@@ -1051,9 +1051,9 @@ public class OperationSetBasicTelephonySipImpl
CallPeerSipImpl existingPeer
= activeCallsRepository.findCallPeer(dialog);
- OperationSetAutoAnswerSipImpl autoAnswerOpSet =
- (OperationSetAutoAnswerSipImpl)
- protocolProvider.getOperationSet(OperationSetBasicAutoAnswer.class);
+ OperationSetAutoAnswerSipImpl autoAnswerOpSet
+ = (OperationSetAutoAnswerSipImpl) protocolProvider.getOperationSet(
+ OperationSetBasicAutoAnswer.class);
if(existingPeer == null)
{
@@ -1067,7 +1067,7 @@ public class OperationSetBasicTelephonySipImpl
// checks for forward of call, if no further processing
// is needed return
if(autoAnswerOpSet != null
- && autoAnswerOpSet.preCallCheck(invite, serverTransaction))
+ && autoAnswerOpSet.forwardCall(invite, serverTransaction))
return;
//this is a brand new call (not a transferred one)
@@ -1125,12 +1125,12 @@ public class OperationSetBasicTelephonySipImpl
return;
}
-
- // checks for auto answering of call, if no further processing
- // is needed return
- if(autoAnswerOpSet != null
- && autoAnswerOpSet.followCallCheck(invite, call))
- return;
+ // Manages auto answer with "audio only", or "audio / video"
+ // answer.
+ if(autoAnswerOpSet != null)
+ {
+ autoAnswerOpSet.autoAnswer(call);
+ }
}
else
{
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java
index f7bc2e9..6602f4a 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java
@@ -419,9 +419,8 @@ public class ProtocolProviderServiceSipImpl
OperationSetAdvancedTelephony.class,
opSetBasicTelephonySipImpl);
- OperationSetAutoAnswerSipImpl autoAnswerOpSet =
- new OperationSetAutoAnswerSipImpl(
- opSetBasicTelephonySipImpl);
+ OperationSetAutoAnswerSipImpl autoAnswerOpSet
+ = new OperationSetAutoAnswerSipImpl(this);
addSupportedOperationSet(
OperationSetBasicAutoAnswer.class, autoAnswerOpSet);
addSupportedOperationSet(
diff --git a/src/net/java/sip/communicator/service/protocol/AbstractOperationSetBasicAutoAnswer.java b/src/net/java/sip/communicator/service/protocol/AbstractOperationSetBasicAutoAnswer.java
new file mode 100644
index 0000000..f90e4b1
--- /dev/null
+++ b/src/net/java/sip/communicator/service/protocol/AbstractOperationSetBasicAutoAnswer.java
@@ -0,0 +1,298 @@
+/*
+ * 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.service.protocol;
+
+import net.java.sip.communicator.service.protocol.event.*;
+import net.java.sip.communicator.util.*;
+
+import java.util.*;
+
+/**
+ * An Abstract Operation Set defining option to unconditionally auto answer
+ * incoming calls.
+ *
+ * @author Damian Minkov
+ * @author Vincent Lucas
+ */
+public abstract class AbstractOperationSetBasicAutoAnswer
+ implements OperationSetBasicAutoAnswer
+{
+ /**
+ * Our class logger.
+ */
+ private static final Logger logger
+ = Logger.getLogger(AbstractOperationSetBasicAutoAnswer.class);
+
+ /**
+ * The parent Protocol Provider.
+ */
+ protected final ProtocolProviderService protocolProvider;
+
+ /**
+ * Should we unconditionally answer.
+ */
+ protected boolean answerUnconditional = false;
+
+ /**
+ * Should we answer video calls with video.
+ */
+ protected boolean answerWithVideo = false;
+
+ /**
+ * Creates this operation set, loads stored values, populating
+ * local variable settings.
+ *
+ * @param protocolProvider the parent Protocol Provider.
+ */
+ public AbstractOperationSetBasicAutoAnswer(
+ ProtocolProviderService protocolProvider)
+ {
+ this.protocolProvider = protocolProvider;
+
+ // init values from account props
+ load();
+ }
+
+ /**
+ * Load values from account properties.
+ */
+ protected void load()
+ {
+ AccountID acc = protocolProvider.getAccountID();
+
+ answerUnconditional
+ = acc.getAccountPropertyBoolean(AUTO_ANSWER_UNCOND_PROP, false);
+ answerWithVideo
+ = acc.getAccountPropertyBoolean(AUTO_ANSWER_WITH_VIDEO_PROP, false);
+ }
+
+ /**
+ * Saves values to account properties.
+ */
+ protected abstract void save();
+
+ /**
+ * Clear local settings.
+ */
+ protected void clearLocal()
+ {
+ this.answerUnconditional = false;
+ }
+
+ /**
+ * Clear any previous settings.
+ */
+ public void clear()
+ {
+ clearLocal();
+
+ this.answerWithVideo = false;
+
+ save();
+ }
+
+ /**
+ * Makes a check after creating call locally, should we answer it.
+ *
+ * @param call The new incoming call to auto-answer if needed.
+ * @param isVideoCall Indicates if the remote peer which has created this
+ * call wish to have a video call.
+ *
+ * @return <tt>true</tt> if we have processed and no further processing is
+ * needed, <tt>false</tt> otherwise.
+ */
+ public boolean autoAnswer(Call call, boolean isVideoCall)
+ {
+ if(answerUnconditional || satisfyAutoAnswerConditions(call))
+ {
+ this.answerCall(call, isVideoCall);
+ return true;
+ }
+ return false;
+ }
+
+
+ /**
+ * Answers call if peer in correct state or wait for it.
+ *
+ * @param call The new incoming call to auto-answer if needed.
+ * @param isVideoCall Indicates if the remote peer which has created this
+ * call wish to have a video call.
+ */
+ protected void answerCall(Call call, boolean isVideoCall)
+ {
+ // We are here because we satisfy the conditional, or unconditional is
+ // true.
+ Iterator<? extends CallPeer> peers = call.getCallPeers();
+
+ while (peers.hasNext())
+ {
+ new AutoAnswerThread(peers.next(), isVideoCall);
+ }
+ }
+
+ /**
+ * Checks if the call satisfy the auto answer conditions.
+ *
+ * @param call The new incoming call to auto-answer if needed.
+ *
+ * @return <tt>true</tt> if the call satisfy the auto answer conditions.
+ * <tt>False</tt> otherwise.
+ */
+ protected abstract boolean satisfyAutoAnswerConditions(Call call);
+
+ /**
+ * Sets the auto answer option to unconditionally answer all incoming calls.
+ */
+ public void setAutoAnswerUnconditional()
+ {
+ clearLocal();
+
+ this.answerUnconditional = true;
+
+ save();
+ }
+
+ /**
+ * Is the auto answer option set to unconditionally
+ * answer all incoming calls.
+ *
+ * @return is auto answer set to unconditional.
+ */
+ public boolean isAutoAnswerUnconditionalSet()
+ {
+ return answerUnconditional;
+ }
+
+ /**
+ * Sets the auto answer with video to video calls.
+ *
+ * @param answerWithVideo A boolean set to true to activate the auto answer
+ * with video when receiving a video call. False otherwise.
+ */
+ public void setAutoAnswerWithVideo(boolean answerWithVideo)
+ {
+ this.answerWithVideo = answerWithVideo;
+ this.save();
+ }
+
+ /**
+ * Returns if the auto answer with video to video calls is activated.
+ *
+ * @return A boolean set to true if the auto answer with video when
+ * receiving a video call is activated. False otherwise.
+ */
+ public boolean isAutoAnswerWithVideoSet()
+ {
+ return this.answerWithVideo;
+ }
+
+ /**
+ * Waits for peer to switch into INCOMING_CALL state, before
+ * auto-answering the call in a new thread.
+ */
+ private class AutoAnswerThread
+ extends CallPeerAdapter
+ implements Runnable
+ {
+ /**
+ * The call peer which has generated the call.
+ */
+ private CallPeer peer;
+
+ /**
+ * Indicates if the remote peer which has created this call wish to have
+ * a video call.
+ */
+ private boolean isVideoCall;
+
+ /**
+ * Waits for peer to switch into INCOMING_CALL state, before
+ * auto-answering the call in a new thread.
+ *
+ * @param peer The call peer which has generated the call.
+ * @param isVideoCall Indicates if the remote peer which has created
+ * this call wish to have a video call.
+ */
+ public AutoAnswerThread(CallPeer peer, boolean isVideoCall)
+ {
+ this.peer = peer;
+ this.isVideoCall = isVideoCall;
+
+ if (peer.getState() == CallPeerState.INCOMING_CALL)
+ {
+ new Thread(this).start();
+ }
+ else
+ {
+ peer.addCallPeerListener(this);
+ }
+
+ }
+
+ /**
+ * Answers the call.
+ */
+ public void run()
+ {
+ OperationSetBasicAutoAnswer opSetBasicAutoAnswer
+ = protocolProvider.getOperationSet(
+ OperationSetBasicAutoAnswer.class);
+ OperationSetBasicTelephony opSetBasicTelephony
+ = protocolProvider.getOperationSet(
+ OperationSetBasicTelephony.class);
+ OperationSetVideoTelephony opSetVideoTelephony
+ = protocolProvider.getOperationSet(
+ OperationSetVideoTelephony.class);
+ try
+ {
+ // If this is a video call and that the user has configured to
+ // answer it with wideo, then create a video call.
+ if(this.isVideoCall
+ && answerWithVideo
+ && opSetVideoTelephony != null)
+ {
+ System.out.println("CHENZO: VIDEO");
+ opSetVideoTelephony.answerVideoCallPeer(peer);
+ }
+ // Else sends only audio to the repote peer (the remote peer is
+ // still able to send us its video stream).
+ else if(opSetBasicTelephony != null)
+ {
+ System.out.println("CHENZO: AUDIO");
+ opSetBasicTelephony.answerCallPeer(peer);
+ }
+ }
+ catch (OperationFailedException e)
+ {
+ logger.error("Could not answer to : " + peer
+ + " caused by the following exception: " + e);
+ }
+ }
+
+ /**
+ * If we peer was not in proper state wait for it and then answer.
+ *
+ * @param evt the <tt>CallPeerChangeEvent</tt> instance containing the
+ */
+ public void peerStateChanged(CallPeerChangeEvent evt)
+ {
+ CallPeerState newState = (CallPeerState) evt.getNewValue();
+
+ if (newState == CallPeerState.INCOMING_CALL)
+ {
+ evt.getSourceCallPeer().removeCallPeerListener(this);
+ new Thread(this).start();
+ }
+ else if (newState == CallPeerState.DISCONNECTED
+ || newState == CallPeerState.FAILED)
+ {
+ evt.getSourceCallPeer().removeCallPeerListener(this);
+ }
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/service/protocol/OperationSetBasicAutoAnswer.java b/src/net/java/sip/communicator/service/protocol/OperationSetBasicAutoAnswer.java
index cdb3b46..ca7ad65 100644
--- a/src/net/java/sip/communicator/service/protocol/OperationSetBasicAutoAnswer.java
+++ b/src/net/java/sip/communicator/service/protocol/OperationSetBasicAutoAnswer.java
@@ -22,6 +22,12 @@ public interface OperationSetBasicAutoAnswer
"AUTO_ANSWER_UNCONDITIONAL";
/**
+ * Auto answer video calls with video account property.
+ */
+ public static final String AUTO_ANSWER_WITH_VIDEO_PROP =
+ "AUTO_ANSWER_WITH_VIDEO";
+
+ /**
* Sets the auto answer option to unconditionally answer all incoming calls.
*/
public void setAutoAnswerUnconditional();
@@ -37,4 +43,21 @@ public interface OperationSetBasicAutoAnswer
* Clear any previous settings.
*/
public void clear();
+
+ /**
+ * Sets the auto answer with video to video calls.
+ *
+ * @param answerWithVideo A boolean set to true to activate the auto answer
+ * with video when receiving a video call. False otherwise.
+ */
+ public void setAutoAnswerWithVideo(boolean answerWithVideo);
+
+ /**
+ * Returns if the auto answer with video to video calls is activated.
+ *
+ * @return A boolean set to true if the auto answer with video when
+ * receiving a video call is activated. False otherwise.
+ */
+ public boolean isAutoAnswerWithVideoSet();
+
}