From 4821958ecddd49fb8170e7b6ccc7c17d454f06e2 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Fri, 7 Dec 2012 14:26:59 +0100 Subject: [PATCH] Improve audio hack for Galaxy S. --- coreapi/linphonecore_jni.cc | 11 +-- .../org/linphone/core/LinphoneCore.java | 20 ++++-- .../org/linphone/core/LinphoneCoreImpl.java | 68 ++++++++++++++++--- mediastreamer2 | 2 +- 4 files changed, 82 insertions(+), 19 deletions(-) diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index e6d44997..99d46fb1 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -2079,10 +2079,13 @@ extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_soundResourcesLocked // Needed by Galaxy S (can't switch to/from speaker while playing and still keep mic working) // Implemented directly in msandroid.cpp (sound filters for Android). -extern "C" void msandroid_hack_speaker_state(bool speakerOn); - -extern "C" void Java_org_linphone_LinphoneManager_hackSpeakerState(JNIEnv* env,jobject thiz,jboolean speakerOn){ - msandroid_hack_speaker_state(speakerOn); +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_forceSpeakerState(JNIEnv *env, jobject thiz, jlong ptr, jboolean speakerOn) { + LinphoneCore *lc = (LinphoneCore *)ptr; + LinphoneCall *call = linphone_core_get_current_call(lc); + if (call && call->audiostream && call->audiostream->soundread) { + bool_t on = speakerOn; + ms_filter_call_method(call->audiostream->soundread, MS_AUDIO_CAPTURE_FORCE_SPEAKER_STATE, &on); + } } // End Galaxy S hack functions diff --git a/java/common/org/linphone/core/LinphoneCore.java b/java/common/org/linphone/core/LinphoneCore.java index c1da356b..ba3802aa 100644 --- a/java/common/org/linphone/core/LinphoneCore.java +++ b/java/common/org/linphone/core/LinphoneCore.java @@ -278,6 +278,12 @@ public interface LinphoneCore { return mValue; } } + + /** + * Set the context of creation of the LinphoneCore. + */ + public void setContext(Object context); + /** * clear all added proxy configs */ @@ -417,7 +423,9 @@ public interface LinphoneCore { * @throws LinphoneCoreException */ public void deferCallUpdate(LinphoneCall aCall) throws LinphoneCoreException; - + + public void startRinging(); + /** * @return a list of LinphoneCallLog */ @@ -472,7 +480,7 @@ public interface LinphoneCore { * @return true is mic is muted */ boolean isMicMuted(); - + /** * Initiate a dtmf signal if in call * @param number @@ -524,7 +532,7 @@ public interface LinphoneCore { */ boolean isEchoCancellationEnabled(); /** - * Get echo limiter status (another method of doing echo suppressionn, more brute force) + * Get echo limiter status (another method of doing echo suppression, more brute force) * @return true if echo limiter is enabled */ boolean isEchoLimiterEnabled(); @@ -537,13 +545,13 @@ public interface LinphoneCore { */ Transports getSignalingTransportPorts(); /** - * not implemented + * Activates or deactivates the speaker. * @param value */ void enableSpeaker(boolean value); /** - * not implemented - * @return + * Tells whether the speaker is activated. + * @return true if speaker enabled, false otherwise */ boolean isSpeakerEnabled(); /** diff --git a/java/impl/org/linphone/core/LinphoneCoreImpl.java b/java/impl/org/linphone/core/LinphoneCoreImpl.java index c00c9a37..83f6d20d 100644 --- a/java/impl/org/linphone/core/LinphoneCoreImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreImpl.java @@ -18,14 +18,25 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.linphone.core; +import static android.media.AudioManager.MODE_IN_CALL; +import static android.media.AudioManager.MODE_RINGTONE; +import android.content.Context; +import android.media.AudioManager; + import java.io.File; import java.io.IOException; +import org.linphone.core.LinphoneCall.State; +import org.linphone.mediastream.video.capture.hwconf.Hacks; + class LinphoneCoreImpl implements LinphoneCore { private final LinphoneCoreListener mListener; //to make sure to keep a reference on this object private long nativePtr = 0; + private Context mContext = null; + private AudioManager mAudioManager = null; + private boolean mSpeakerEnabled = false; private native long newLinphoneCore(LinphoneCoreListener listener,String userConfig,String factoryConfig,Object userdata); private native void iterate(long nativePtr); private native long getDefaultProxyConfig(long nativePtr); @@ -130,14 +141,24 @@ class LinphoneCoreImpl implements LinphoneCore { protected void finalize() throws Throwable { } - + + private boolean contextInitialized() { + if (mContext == null) { + Log.e("Context of LinphoneCore has not been initialized, call setContext() after creating LinphoneCore."); + return false; + } + return true; + } + public void setContext(Object context) { + mContext = (Context)context; + mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + } + public synchronized void addAuthInfo(LinphoneAuthInfo info) { isValid(); addAuthInfo(nativePtr,((LinphoneAuthInfoImpl)info).nativePtr); } - - public synchronized LinphoneProxyConfig getDefaultProxyConfig() { isValid(); long lNativePtr = getDefaultProxyConfig(nativePtr); @@ -201,7 +222,6 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized void acceptCall(LinphoneCall aCall) { isValid(); acceptCall(nativePtr,((LinphoneCallImpl)aCall).nativePtr); - } public synchronized LinphoneCallLog[] getCallLogs() { isValid(); @@ -235,6 +255,7 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized void muteMic(boolean isMuted) { muteMic(nativePtr,isMuted); } + public synchronized LinphoneAddress interpretUrl(String destination) throws LinphoneCoreException { long lAddress = interpretUrl(nativePtr,destination); if (lAddress != 0) { @@ -301,13 +322,37 @@ class LinphoneCoreImpl implements LinphoneCore { // TODO Auto-generated method stub } + + private void applyAudioHacks() { + if (Hacks.needGalaxySAudioHack()) { + /* The microphone gain is way too high on the Galaxy S so correct it here. */ + setMicrophoneGain(-9.0f); + } + } + private void setAudioModeIncallForGalaxyS() { + if (!contextInitialized()) return; + mAudioManager.setMode(MODE_IN_CALL); + } + public void routeAudioToSpeakerHelper(boolean speakerOn) { + if (!contextInitialized()) return; + if (Hacks.needGalaxySAudioHack()) + setAudioModeIncallForGalaxyS(); + mAudioManager.setSpeakerphoneOn(speakerOn); + } + private native void forceSpeakerState(long nativePtr, boolean speakerOn); public void enableSpeaker(boolean value) { - // TODO Auto-generated method stub - + final LinphoneCall call = getCurrentCall(); + mSpeakerEnabled = value; + applyAudioHacks(); + if (call != null && call.getState() == State.StreamsRunning && Hacks.needGalaxySAudioHack()) { + Log.d("Hack to have speaker=", value, " while on call"); + forceSpeakerState(nativePtr, value); + } else { + routeAudioToSpeakerHelper(value); + } } public boolean isSpeakerEnabled() { - // TODO Auto-generated method stub - return false; + return mSpeakerEnabled; } public synchronized void playDtmf(char number, int duration) { playDtmf(nativePtr,number, duration); @@ -697,6 +742,13 @@ class LinphoneCoreImpl implements LinphoneCore { throws LinphoneCoreException { deferCallUpdate(nativePtr, getCallPtr(aCall)); } + + public synchronized void startRinging() { + if (!contextInitialized()) return; + if (Hacks.needGalaxySAudioHack()) { + mAudioManager.setMode(MODE_RINGTONE); + } + } private native void setVideoPolicy(long nativePtr, boolean autoInitiate, boolean autoAccept); public synchronized void setVideoPolicy(boolean autoInitiate, boolean autoAccept) { diff --git a/mediastreamer2 b/mediastreamer2 index 01dcf8ba..07e0e720 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 01dcf8babee2166886008a4c0748fcb7d85e7c24 +Subproject commit 07e0e720ee7a9d3c34d28430bc15319ad27b3d8b -- 2.39.2