Improve Galaxy S support. Add hack preferences.

- Switching to earpiece/speaker shouldn't mute the mic anymore
- Enable hidden audio hacks by removing "android:layout="@layout/hidden"
  from "pref_audio_hacks_title" PreferenceScreen.
This commit is contained in:
Guillaume Beraudo 2011-04-20 15:41:52 +02:00
parent bbbb79a350
commit fcd3b8d387
11 changed files with 110 additions and 42 deletions

View file

@ -1,6 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="pref_audio_use_specific_mode_key">pref_audio_use_specific_mode_key</string>
<string name="pref_audio_hacks_use_galaxys_hack_key">pref_audio_hacks_use_galaxys_hack_key</string>
<string name="pref_audio_hacks_use_routing_api_key">pref_audio_hacks_use_routing_api_key</string>
<string name="pref_audio_soft_volume_key">pref_audio_soft_volume_key</string> <string name="pref_audio_soft_volume_key">pref_audio_soft_volume_key</string>
<string name="pref_ipv6_key">pref_ipv6_key</string> <string name="pref_ipv6_key">pref_ipv6_key</string>

View file

@ -1,6 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="pref_audio_hacks_title">Audio hacks</string>
<string name="pref_audio_use_specific_mode_title">Use specific mode hack</string>
<string name="pref_audio_use_specific_mode_summary">0=MODE_NORMAL (default), 2=MODE_IN_CALL</string>
<string name="pref_audio_hacks_use_routing_api_title">Use routing API hack</string>
<string name="pref_audio_hacks_use_galaxys_hack_title">Use Galaxy S audio hack</string>
<string name="pref_audio_soft_volume_title">Use software volume</string> <string name="pref_audio_soft_volume_title">Use software volume</string>
<string name="pref_ipv6_title">Use ipv6 instead of ipv4</string> <string name="pref_ipv6_title">Use ipv6 instead of ipv4</string>

View file

@ -135,6 +135,18 @@
<CheckBoxPreference android:key="@string/pref_transport_use_standard_ports_key" <CheckBoxPreference android:key="@string/pref_transport_use_standard_ports_key"
android:title="@string/pref_transport_use_standard_ports"/> android:title="@string/pref_transport_use_standard_ports"/>
</PreferenceScreen> </PreferenceScreen>
<PreferenceScreen android:title="@string/pref_audio_hacks_title"
android:layout="@layout/hidden">
<CheckBoxPreference android:key="@string/pref_audio_hacks_use_routing_api_key"
android:title="@string/pref_audio_hacks_use_routing_api_title" />
<CheckBoxPreference android:key="@string/pref_audio_hacks_use_galaxys_hack_key"
android:title="@string/pref_audio_hacks_use_galaxys_hack_title" />
<EditTextPreference android:key="@string/pref_audio_use_specific_mode_key"
android:title="@string/pref_audio_use_specific_mode_title"
android:summary="@string/pref_audio_use_specific_mode_summary"
android:defaultValue="0" android:numeric="integer" />
</PreferenceScreen>
</PreferenceCategory> </PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>

View file

@ -18,6 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
package org.linphone; package org.linphone;
import static android.media.AudioManager.ROUTE_EARPIECE;
import static android.media.AudioManager.MODE_IN_CALL; import static android.media.AudioManager.MODE_IN_CALL;
import static android.media.AudioManager.MODE_NORMAL; import static android.media.AudioManager.MODE_NORMAL;
import static android.media.AudioManager.MODE_RINGTONE; import static android.media.AudioManager.MODE_RINGTONE;
@ -111,6 +112,7 @@ public final class LinphoneManager implements LinphoneCoreListener {
private LinphoneCore mLc; private LinphoneCore mLc;
private int mPhoneOrientation; private int mPhoneOrientation;
private static Transports initialTransports; private static Transports initialTransports;
private static LinphonePreferenceManager lpm = LinphonePreferenceManager.getInstance();
@ -171,14 +173,38 @@ public final class LinphoneManager implements LinphoneCoreListener {
private boolean hasCamera; private boolean hasCamera;
private synchronized void routeAudioToSpeakerHelper(boolean speakerOn) {
LinphoneCall call = mLc.getCurrentCall();
boolean paused = false;
if (call != null && call.getState() == State.StreamsRunning && Hacks.needPausingCallForSpeakers()) {
Log.d(TAG, "Hack pausing call to have speaker="+speakerOn);
mLc.pauseCall(call);
paused = true;
}
if (Hacks.needGalaxySAudioHack() || lpm.useGalaxySHack())
setAudioModeIncallForGalaxyS();
if (lpm.useSpecificAudioModeHack() != -1)
mAudioManager.setMode(lpm.useSpecificAudioModeHack());
if (Hacks.needRoutingAPI() || lpm.useAudioRoutingAPIHack()) {
mAudioManager.setRouting(
MODE_NORMAL,
speakerOn? ROUTE_SPEAKER : ROUTE_EARPIECE,
AudioManager.ROUTE_ALL);
} else {
mAudioManager.setSpeakerphoneOn(speakerOn);
}
if (paused) {
Log.d(TAG, "Hack resuming call to have speaker="+speakerOn);
mLc.resumeCall(call);
}
}
public void routeAudioToSpeaker() { public void routeAudioToSpeaker() {
if (Integer.parseInt(Build.VERSION.SDK) <= 4 /*<donut*/) { routeAudioToSpeakerHelper(true);
mAudioManager.setRouting(MODE_NORMAL,
AudioManager.ROUTE_SPEAKER, AudioManager.ROUTE_ALL);
} else {
mAudioManager.setSpeakerphoneOn(true);
}
if (mLc.isIncall()) { if (mLc.isIncall()) {
/*disable EC*/ /*disable EC*/
mLc.getCurrentCall().enableEchoCancellation(false); mLc.getCurrentCall().enableEchoCancellation(false);
@ -188,13 +214,7 @@ public final class LinphoneManager implements LinphoneCoreListener {
} }
public void routeAudioToReceiver() { public void routeAudioToReceiver() {
if (Integer.parseInt(Build.VERSION.SDK) <=4 /*<donut*/) { routeAudioToSpeakerHelper(false);
mAudioManager.setRouting(MODE_NORMAL,
AudioManager.ROUTE_EARPIECE, AudioManager.ROUTE_ALL);
} else {
mAudioManager.setSpeakerphoneOn(false);
}
if (mLc.isIncall()) { if (mLc.isIncall()) {
//Restore default value //Restore default value
mLc.getCurrentCall().enableEchoCancellation(mLc.isEchoCancellationEnabled()); mLc.getCurrentCall().enableEchoCancellation(mLc.isEchoCancellationEnabled());
@ -689,7 +709,7 @@ public final class LinphoneManager implements LinphoneCoreListener {
if (mCurrentCallState == IncomingReceived) { if (mCurrentCallState == IncomingReceived) {
//previous state was ringing, so stop ringing //previous state was ringing, so stop ringing
stopRinging(); stopRinging();
//routeAudioToReceiver(); routeAudioToReceiver();
} }
if (state == CallEnd || state == Error) { if (state == CallEnd || state == Error) {
@ -769,9 +789,7 @@ public final class LinphoneManager implements LinphoneCoreListener {
mVibrator.cancel(); mVibrator.cancel();
} }
if (Hacks.needGalaxySAudioHack()) { // You may need to call galaxys audio hack after this method
mAudioManager.setMode(MODE_IN_CALL);
}
} }
@ -802,16 +820,8 @@ public final class LinphoneManager implements LinphoneCoreListener {
} }
public void setAudioModeIncallForGalaxyS() { public void setAudioModeIncallForGalaxyS() {
if (!Hacks.needGalaxySAudioHack()) return; stopRinging();
mAudioManager.setMode(MODE_IN_CALL);
try {
stopRinging();
Thread.sleep(100);
mAudioManager.setMode(AudioManager.MODE_IN_CALL);
Thread.sleep(100);
} catch (InterruptedException e) {
/* ops */
}
} }
// Called on first launch only // Called on first launch only
@ -852,7 +862,9 @@ public final class LinphoneManager implements LinphoneCoreListener {
} }
public boolean acceptCallIfIncomingPending() throws LinphoneCoreException { public boolean acceptCallIfIncomingPending() throws LinphoneCoreException {
setAudioModeIncallForGalaxyS(); if (Hacks.needGalaxySAudioHack() || lpm.useGalaxySHack())
setAudioModeIncallForGalaxyS();
if (mLc.isInComingInvitePending()) { if (mLc.isInComingInvitePending()) {
mLc.acceptCall(mLc.getCurrentCall()); mLc.acceptCall(mLc.getCurrentCall());
return true; return true;

View file

@ -51,4 +51,18 @@ public class LinphonePreferenceManager {
return p.getBoolean( return p.getBoolean(
getString(R.string.pref_audio_soft_volume_key), false); getString(R.string.pref_audio_soft_volume_key), false);
} }
public boolean useAudioRoutingAPIHack() {
return p.getBoolean(
getString(R.string.pref_audio_hacks_use_routing_api_key), false);
}
public boolean useGalaxySHack() {
return p.getBoolean(
getString(R.string.pref_audio_hacks_use_galaxys_hack_key), false);
}
public int useSpecificAudioModeHack() {
return Integer.parseInt(p.getString(getString(R.string.pref_audio_use_specific_mode_key), "0"));
}
} }

View file

@ -100,6 +100,8 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
super.onCreate(); super.onCreate();
instance = this; instance = this;
LinphonePreferenceManager.setContext(this); // In case restart after a crash . Main in LinphoneActivity
// Set default preferences // Set default preferences
PreferenceManager.setDefaultValues(this, R.xml.preferences, true); PreferenceManager.setDefaultValues(this, R.xml.preferences, true);
@ -233,7 +235,7 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
} else if (state == LinphoneCall.State.StreamsRunning) { } else if (state == LinphoneCall.State.StreamsRunning) {
if (LinphoneActivity.isInstanciated() if (LinphoneActivity.isInstanciated()
&& getResources().getBoolean(R.bool.use_video_activity) && getResources().getBoolean(R.bool.use_video_activity)
&& LinphoneManager.getLc().getCurrentCall().getCurrentParamsCopy().getVideoEnabled()) { && call.getCurrentParamsCopy().getVideoEnabled()) {
LinphoneActivity.instance().startVideoActivity(); LinphoneActivity.instance().startVideoActivity();
} }
} }

View file

@ -30,9 +30,6 @@ public final class Hacks {
return isGT9000() || isSC02B(); return isGT9000() || isSC02B();
} }
public static boolean needGalaxySAudioHack() {
return isGalaxySOrTab();
}
public static boolean isGalaxySOrTabWithFrontCamera() { public static boolean isGalaxySOrTabWithFrontCamera() {
return isGalaxySOrTab() && !isGalaxySOrTabWithoutFrontCamera(); return isGalaxySOrTab() && !isGalaxySOrTabWithoutFrontCamera();
@ -93,10 +90,23 @@ public final class Hacks {
//sb.append("MANUFACTURER=").append(Build.MANUFACTURER).append("\n"); //sb.append("MANUFACTURER=").append(Build.MANUFACTURER).append("\n");
sb.append("SDK=").append(Build.VERSION.SDK); sb.append("SDK=").append(Build.VERSION.SDK);
Log.d(Version.TAG, sb.toString()); Log.i(Version.TAG, sb.toString());
} }
public static boolean needSoftvolume() { public static boolean needSoftvolume() {
return isGalaxySOrTab(); return isGalaxySOrTab();
} }
public static boolean needRoutingAPI() {
return Version.sdkStrictlyBelow(5) /*<donut*/;
}
public static boolean needGalaxySAudioHack() {
return isGalaxySOrTab() && !isSC02B();
}
public static boolean needPausingCallForSpeakers() {
// return false;
return isGalaxySOrTab() && !isSC02B();
}
} }

View file

@ -96,7 +96,9 @@ class LinphoneCoreImpl implements LinphoneCore {
private native void setSignalingTransportPorts(long nativePtr, int udp, int tcp, int tls); private native void setSignalingTransportPorts(long nativePtr, int udp, int tcp, int tls);
private native void enableIpv6(long nativePtr,boolean enable); private native void enableIpv6(long nativePtr,boolean enable);
private native void adjustSoftwareVolume(long nativePtr,int db); private native void adjustSoftwareVolume(long nativePtr,int db);
private native int pauseCall(long nativePtr, long callPtr);
private native int pauseAllCalls(long nativePtr);
private native int resumeCall(long nativePtr, long callPtr);
LinphoneCoreImpl(LinphoneCoreListener listener, File userConfig,File factoryConfig,Object userdata) throws IOException { LinphoneCoreImpl(LinphoneCoreListener listener, File userConfig,File factoryConfig,Object userdata) throws IOException {
mListener=listener; mListener=listener;
nativePtr = newLinphoneCore(listener,userConfig.getCanonicalPath(),factoryConfig.getCanonicalPath(),userdata); nativePtr = newLinphoneCore(listener,userConfig.getCanonicalPath(),factoryConfig.getCanonicalPath(),userdata);
@ -472,4 +474,13 @@ class LinphoneCoreImpl implements LinphoneCore {
adjustSoftwareVolume(nativePtr, i); adjustSoftwareVolume(nativePtr, i);
} }
public synchronized boolean pauseCall(LinphoneCall call) {
return 0 == pauseCall(nativePtr, ((LinphoneCallImpl) call).nativePtr);
}
public synchronized boolean resumeCall(LinphoneCall call) {
return 0 == resumeCall(nativePtr, ((LinphoneCallImpl) call).nativePtr);
}
public synchronized boolean pauseAllCalls() {
return 0 == pauseAllCalls(nativePtr);
}
} }

View file

@ -41,15 +41,12 @@ public class MuteMicButton extends ToggleImageButton implements OnCheckedChangeL
} }
public void setMicMuted(boolean state) { public void setMicMuted(boolean state) {
setChecked(state); if (state != isChecked())
setChecked(state);
} }
public void onCheckedChanged(ToggleImageButton button, boolean checked) { public void onCheckedChanged(ToggleImageButton button, boolean checked) {
if (checked) { LinphoneManager.getLc().muteMic(checked);
LinphoneManager.getLc().muteMic(true);
} else {
LinphoneManager.getLc().muteMic(false);
}
} }
} }

View file

@ -41,7 +41,8 @@ public class SpeakerButton extends ToggleImageButton implements OnCheckedChangeL
} }
public void setSpeakerOn(boolean state) { public void setSpeakerOn(boolean state) {
setChecked(state); if (state != isChecked())
setChecked(state);
} }

@ -1 +1 @@
Subproject commit ed8a2f44d51c9a2c10fe0f531b4f7a2640aaa68c Subproject commit adc7838132946ce02074d686dd581eb86a468228