diff --git a/res/values/strings.xml b/res/values/strings.xml
index 896ccecbf..438e4e3ff 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -227,6 +227,10 @@
SRTP
ZRTP
+Your correspondent would like to switch to video
+Accept video
+Deny video
+
pref_nb_accounts_extra
pref_default_account
SIP Accounts
diff --git a/src/org/linphone/IncallActivity.java b/src/org/linphone/IncallActivity.java
index 057a7dcd4..18a636c44 100644
--- a/src/org/linphone/IncallActivity.java
+++ b/src/org/linphone/IncallActivity.java
@@ -29,9 +29,11 @@ import java.util.List;
import org.linphone.LinphoneSimpleListener.LinphoneOnAudioChangedListener;
import org.linphone.LinphoneSimpleListener.LinphoneOnCallEncryptionChangedListener;
+import org.linphone.LinphoneSimpleListener.LinphoneOnCallStateChangedListener;
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneCall.State;
+import org.linphone.core.LinphoneCallParams;
import org.linphone.core.LinphoneCore.MediaEncryption;
import org.linphone.core.LinphoneCoreException;
import org.linphone.core.Log;
@@ -44,6 +46,7 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
+import android.os.CountDownTimer;
import android.os.Handler;
import android.text.TextUtils;
import android.view.KeyEvent;
@@ -63,6 +66,7 @@ import android.widget.Toast;
*/
public class IncallActivity extends AbstractCalleesActivity implements
LinphoneOnAudioChangedListener,
+ LinphoneOnCallStateChangedListener,
LinphoneOnCallEncryptionChangedListener,
Comparator,
OnLongClickListener,
@@ -73,12 +77,23 @@ public class IncallActivity extends AbstractCalleesActivity implements
private static final int numpadDialogId = 1;
private static final int addCallId = 1;
private static final int transferCallId = 2;
+ private static final int promptVideoId = 3;
+ private static IncallActivity instance;
+ private CountDownTimer timer;
public static boolean active;
@Override protected void setActive(boolean a) {active = a;}
@Override protected boolean isActive() {return active;}
-
+ public static boolean isReady() {
+ return instance!=null;
+ }
+
+ static IncallActivity instance() {
+ if (isReady()) return instance;
+ return null;
+ }
+
private void pauseCurrentCallOrLeaveConference() {
LinphoneCall call = lc().getCurrentCall();
if (call != null && !call.isInConference()) {
@@ -99,7 +114,8 @@ public class IncallActivity extends AbstractCalleesActivity implements
return;
}
setContentView(R.layout.incall_layout);
-
+ instance = this;
+
mAllowTransfers = getResources().getBoolean(R.bool.allow_transfers);
findViewById(R.id.addCall).setOnClickListener(this);
@@ -117,8 +133,7 @@ public class IncallActivity extends AbstractCalleesActivity implements
enableView(mConferenceVirtualCallee, R.id.conf_header_details, this, true);
- boolean mMayDoVideo = Version.isVideoCapable()
- && LinphoneManager.getInstance().isVideoEnabled();
+ boolean mMayDoVideo = Version.isVideoCapable() && LinphoneManager.getInstance().isVideoEnabled();
if (mMayDoVideo) {
findViewById(R.id.conf_simple_video).setOnClickListener(this);
} else {
@@ -178,22 +193,63 @@ public class IncallActivity extends AbstractCalleesActivity implements
view.setVisibility(VISIBLE);
}
+ private void acceptCallUpdate(boolean accept, int id) {
+ removeDialog(id);
+ timer.cancel();
+
+ LinphoneCall call = LinphoneManager.getLc().getCurrentCall();
+ if (call == null)
+ return;
+
+ LinphoneCallParams params = call.getCurrentParamsCopy();
+ if (accept) {
+ params.setVideoEnabled(true);
+ LinphoneManager.getLc().enableVideo(true, true);
+ }
+
+ try {
+ LinphoneManager.getLc().acceptCallUpdate(call, params);
+ } catch (LinphoneCoreException e) {
+ e.printStackTrace();
+ }
+
+ updateUI();
+ }
@Override
+ //FIXME : Store texts into resources
protected Dialog onCreateDialog(final int id) {
switch (id) {
+ case promptVideoId:
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.dynamic_video_asking);
+ builder.setNegativeButton(R.string.dynamic_video_deny, new
+ DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton)
+ {
+ acceptCallUpdate(false, id);
+ }
+ });
+ builder.setPositiveButton(R.string.dynamic_video_accept, new
+ DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton)
+ {
+ acceptCallUpdate(true, id);
+ }
+ });
+ return builder.create();
case numpadDialogId:
Numpad numpad = new Numpad(this, true);
return new AlertDialog.Builder(this).setView(numpad)
// .setIcon(R.drawable.logo_linphone_57x57)
// .setTitle("Send DTMFs")
- .setPositiveButton(getString(R.string.close_button_text), new
+ .setPositiveButton(R.string.close_button_text, new
DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton)
- {
- dismissDialog(id);
- }
- })
+ public void onClick(DialogInterface dialog, int whichButton)
+ {
+ dismissDialog(id);
+ }
+ })
.create();
default:
throw new IllegalArgumentException("unkown dialog id " + id);
@@ -740,4 +796,29 @@ public class IncallActivity extends AbstractCalleesActivity implements
});
}
+ @Override
+ public void onCallStateChanged(LinphoneCall call, final State state, String message) {
+ if (state == State.CallUpdatedByRemote) {
+ // If the correspondent proposes video while audio call
+ boolean remoteVideo = call.getRemoteParams().getVideoEnabled();
+ boolean localVideo = call.getCurrentParamsCopy().getVideoEnabled();
+ boolean autoAcceptCameraPolicy = LinphoneManager.getInstance().isAutoAcceptCamera();
+ if (remoteVideo && !localVideo && !autoAcceptCameraPolicy && !LinphoneManager.getLc().isInConference()) {
+ mHandler.post(new Runnable() {
+ public void run() {
+ showDialog(promptVideoId);
+ // We let 30 secs for the user to decide
+ timer = new CountDownTimer(30000, 1000) {
+ public void onTick(long millisUntilFinished) { }
+
+ public void onFinish() {
+ removeDialog(promptVideoId);
+ }
+ }.start();
+ }
+ });
+ }
+ }
+ super.onCallStateChanged(call, state, message);
+ }
}
diff --git a/src/org/linphone/LinphoneService.java b/src/org/linphone/LinphoneService.java
index b3103987f..57d8694a7 100644
--- a/src/org/linphone/LinphoneService.java
+++ b/src/org/linphone/LinphoneService.java
@@ -25,13 +25,14 @@ import java.lang.reflect.Method;
import org.linphone.LinphoneManager.NewOutgoingCallUiListener;
import org.linphone.LinphoneSimpleListener.LinphoneServiceListener;
import org.linphone.core.LinphoneCall;
+import org.linphone.core.LinphoneCall.State;
import org.linphone.core.LinphoneCore;
+import org.linphone.core.LinphoneCore.GlobalState;
+import org.linphone.core.LinphoneCore.RegistrationState;
+import org.linphone.core.LinphoneCoreException;
import org.linphone.core.LinphoneProxyConfig;
import org.linphone.core.Log;
import org.linphone.core.OnlineStatus;
-import org.linphone.core.LinphoneCall.State;
-import org.linphone.core.LinphoneCore.GlobalState;
-import org.linphone.core.LinphoneCore.RegistrationState;
import org.linphone.mediastream.Version;
import android.app.Notification;
@@ -45,12 +46,12 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.media.MediaPlayer;
import android.media.RingtoneManager;
import android.net.Uri;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiManager.WifiLock;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.preference.PreferenceManager;
-import android.net.wifi.WifiManager.WifiLock;
-import android.net.wifi.WifiManager;
/**
*
@@ -381,6 +382,9 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
return DialerActivity.instance();
}
+ private static final LinphoneOnCallStateChangedListener incallListener() {
+ return IncallActivity.instance();
+ }
@@ -447,6 +451,23 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
.setClass(this, LinphoneActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
+
+ if (state == State.CallUpdatedByRemote) {
+ // If the correspondent proposes video while audio call
+ boolean remoteVideo = call.getRemoteParams().getVideoEnabled();
+ boolean localVideo = call.getCurrentParamsCopy().getVideoEnabled();
+ boolean autoAcceptCameraPolicy = LinphoneManager.getInstance().isAutoAcceptCamera();
+ if (remoteVideo && !localVideo && !autoAcceptCameraPolicy) {
+ try {
+ LinphoneManager.getLc().deferCallUpdate(call);
+
+ if (incallListener() != null)
+ incallListener().onCallStateChanged(call, state, message);
+ } catch (LinphoneCoreException e) {
+ e.printStackTrace();
+ }
+ }
+ }
if (state == State.StreamsRunning) {
// Workaround bug current call seems to be updated after state changed to streams running
@@ -461,7 +482,7 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
mHandler.post(new Runnable() {
public void run() {
if (guiListener() != null)
- guiListener().onCallStateChanged(call, state, message);
+ guiListener().onCallStateChanged(call, state, message);
}
});
}
diff --git a/src/org/linphone/core/LinphoneCoreImpl.java b/src/org/linphone/core/LinphoneCoreImpl.java
index 8e2a83008..b79d19306 100644
--- a/src/org/linphone/core/LinphoneCoreImpl.java
+++ b/src/org/linphone/core/LinphoneCoreImpl.java
@@ -589,21 +589,21 @@ class LinphoneCoreImpl implements LinphoneCore {
return (LinphoneCall) findCallFromUri(nativePtr, uri);
}
- public MediaEncryption getMediaEncryption() {
+ public synchronized MediaEncryption getMediaEncryption() {
return MediaEncryption.fromInt(getMediaEncryption(nativePtr));
}
- public boolean isMediaEncryptionMandatory() {
+ public synchronized boolean isMediaEncryptionMandatory() {
return isMediaEncryptionMandatory(nativePtr);
}
- public void setMediaEncryption(MediaEncryption menc) {
+ public synchronized void setMediaEncryption(MediaEncryption menc) {
setMediaEncryption(nativePtr, menc.mValue);
}
- public void setMediaEncryptionMandatory(boolean yesno) {
+ public synchronized void setMediaEncryptionMandatory(boolean yesno) {
setMediaEncryptionMandatory(nativePtr, yesno);
}
private native int getMaxCalls(long nativePtr);
- public int getMaxCalls() {
+ public synchronized int getMaxCalls() {
return getMaxCalls(nativePtr);
}
@Override
@@ -614,61 +614,61 @@ class LinphoneCoreImpl implements LinphoneCore {
}
private native boolean soundResourcesLocked(long nativePtr);
- public boolean soundResourcesLocked() {
+ public synchronized boolean soundResourcesLocked() {
return soundResourcesLocked(nativePtr);
}
private native void setMaxCalls(long nativePtr, int max);
@Override
- public void setMaxCalls(int max) {
+ public synchronized void setMaxCalls(int max) {
setMaxCalls(nativePtr, max);
}
private native boolean isEchoLimiterEnabled(long nativePtr);
@Override
- public boolean isEchoLimiterEnabled() {
+ public synchronized boolean isEchoLimiterEnabled() {
return isEchoLimiterEnabled(nativePtr);
}
private native boolean mediaEncryptionSupported(long nativePtr, int menc);
@Override
- public boolean mediaEncryptionSupported(MediaEncryption menc) {
+ public synchronized boolean mediaEncryptionSupported(MediaEncryption menc) {
return mediaEncryptionSupported(nativePtr,menc.mValue);
}
private native void setPlayFile(long nativePtr, String path);
@Override
- public void setPlayFile(String path) {
+ public synchronized void setPlayFile(String path) {
setPlayFile(nativePtr, path);
}
private native void tunnelAddServerAndMirror(long nativePtr, String host, int port, int mirror, int ms);
@Override
- public void tunnelAddServerAndMirror(String host, int port, int mirror, int ms) {
+ public synchronized void tunnelAddServerAndMirror(String host, int port, int mirror, int ms) {
tunnelAddServerAndMirror(nativePtr, host, port, mirror, ms);
}
private native void tunnelAutoDetect(long nativePtr);
@Override
- public void tunnelAutoDetect() {
+ public synchronized void tunnelAutoDetect() {
tunnelAutoDetect(nativePtr);
}
private native void tunnelCleanServers(long nativePtr);
@Override
- public void tunnelCleanServers() {
+ public synchronized void tunnelCleanServers() {
tunnelCleanServers(nativePtr);
}
private native void tunnelEnable(long nativePtr, boolean enable);
@Override
- public void tunnelEnable(boolean enable) {
+ public synchronized void tunnelEnable(boolean enable) {
tunnelEnable(nativePtr, enable);
}
private native void tunnelEnableLogs(long nativePtr, boolean enable);
@Override
- public void tunnelEnableLogs(boolean enable) {
+ public synchronized void tunnelEnableLogs(boolean enable) {
tunnelEnableLogs(nativePtr, enable);
}
@@ -678,27 +678,27 @@ class LinphoneCoreImpl implements LinphoneCore {
private native void acceptCallWithParams(long nativePtr, long aCall,
long params);
@Override
- public void acceptCallWithParams(LinphoneCall aCall,
+ public synchronized void acceptCallWithParams(LinphoneCall aCall,
LinphoneCallParams params) throws LinphoneCoreException {
acceptCallWithParams(nativePtr, getCallPtr(aCall), getCallParamsPtr(params));
}
private native void acceptCallUpdate(long nativePtr, long aCall, long params);
@Override
- public void acceptCallUpdate(LinphoneCall aCall, LinphoneCallParams params)
+ public synchronized void acceptCallUpdate(LinphoneCall aCall, LinphoneCallParams params)
throws LinphoneCoreException {
acceptCallUpdate(nativePtr, getCallPtr(aCall), getCallParamsPtr(params));
}
private native void deferCallUpdate(long nativePtr, long aCall);
@Override
- public void deferCallUpdate(LinphoneCall aCall)
+ public synchronized void deferCallUpdate(LinphoneCall aCall)
throws LinphoneCoreException {
deferCallUpdate(nativePtr, getCallPtr(aCall));
}
private native void setVideoPolicy(long nativePtr, boolean autoInitiate, boolean autoAccept);
- public void setVideoPolicy(boolean autoInitiate, boolean autoAccept) {
+ public synchronized void setVideoPolicy(boolean autoInitiate, boolean autoAccept) {
setVideoPolicy(nativePtr, autoInitiate, autoAccept);
}
}
diff --git a/submodules/linphone b/submodules/linphone
index dc0361975..6c49da243 160000
--- a/submodules/linphone
+++ b/submodules/linphone
@@ -1 +1 @@
-Subproject commit dc0361975b2b845e66a88e58c8559758b1bd21e1
+Subproject commit 6c49da243ca8e823ff11dd8891af4a60f5330610