From 5fe6a522ba84e58828f5e189eeb8b7304e37f32b Mon Sep 17 00:00:00 2001 From: Guillaume Beraudo Date: Tue, 18 Oct 2011 10:10:24 +0200 Subject: [PATCH] Store and restore user requested audio route. Go back to user requested route when going out of video activity. --- src/org/linphone/ConferenceActivity.java | 37 ++++++++++- src/org/linphone/DialerActivity.java | 9 +-- src/org/linphone/LinphoneActivity.java | 8 ++- src/org/linphone/LinphoneManager.java | 70 +++++++++++++++----- src/org/linphone/LinphoneSimpleListener.java | 5 ++ src/org/linphone/VideoCallActivity.java | 6 +- src/org/linphone/ui/SpeakerButton.java | 4 +- 7 files changed, 108 insertions(+), 31 deletions(-) diff --git a/src/org/linphone/ConferenceActivity.java b/src/org/linphone/ConferenceActivity.java index 270f2d7c4..14e9c18a0 100644 --- a/src/org/linphone/ConferenceActivity.java +++ b/src/org/linphone/ConferenceActivity.java @@ -27,6 +27,7 @@ import java.util.Comparator; import java.util.List; import org.linphone.LinphoneManagerWaitHelper.LinphoneManagerReadyListener; +import org.linphone.LinphoneSimpleListener.LinphoneAudioChangedListener; import org.linphone.LinphoneSimpleListener.LinphoneOnCallStateChangedListener; import org.linphone.core.LinphoneAddress; import org.linphone.core.LinphoneCall; @@ -64,6 +65,7 @@ import android.widget.ToggleButton; */ public class ConferenceActivity extends ListActivity implements LinphoneManagerReadyListener, + LinphoneAudioChangedListener, LinphoneOnCallStateChangedListener, Comparator, OnClickListener { @@ -149,6 +151,10 @@ public class ConferenceActivity extends ListActivity implements updateConfState(); updateSimpleControlButtons(); CalleeListAdapter adapter = (CalleeListAdapter) getListAdapter(); + if (adapter.linphoneCalls.size() != lc().getCallsNb()) { + adapter.linphoneCalls.clear(); + adapter.linphoneCalls.addAll(getInitialCalls()); + } adapter.notifyDataSetInvalidated(); adapter.notifyDataSetChanged(); LinphoneManager.startProximitySensorForActivity(this); @@ -353,9 +359,9 @@ public class ConferenceActivity extends ListActivity implements break; case R.id.toggleSpeaker: if (((ToggleButton) v).isChecked()) { - LinphoneManager.getInstance().routeAudioToSpeaker(); + LinphoneManager.getInstance().routeAudioToSpeaker(true); } else { - LinphoneManager.getInstance().routeAudioToReceiver(); + LinphoneManager.getInstance().routeAudioToReceiver(true); } break; default: @@ -422,6 +428,10 @@ public class ConferenceActivity extends ListActivity implements case R.id.remove_from_conference: lc().removeFromConference(call); break; + case R.id.addVideo: + VideoCallActivity.call = call; + LinphoneActivity.instance().startVideoActivity(); + break; default: throw new RuntimeException("unknown id " + v.getId()); } @@ -561,7 +571,8 @@ public class ConferenceActivity extends ListActivity implements final int numberOfCalls = linphoneCalls.size(); boolean showAddVideo = State.StreamsRunning == state && !isInConference && Version.isVideoCapable() && LinphoneManager.getInstance().isVideoEnabled(); - setVisibility(v, R.id.addVideo, showAddVideo); + View addVideoButton = v.findViewById(R.id.addVideo); + setVisibility(addVideoButton, showAddVideo); boolean statusPaused = state== State.Paused || state == State.PausedByRemote; setVisibility(v, R.id.callee_status_paused, statusPaused); @@ -575,6 +586,7 @@ public class ConferenceActivity extends ListActivity implements resumeButton.setOnClickListener(l); unhookCallButton.setOnClickListener(l); removeFromConfButton.setOnClickListener(l); + addVideoButton.setOnClickListener(l); v.setOnClickListener(new OnClickListener() { public void onClick(View v) { @@ -749,6 +761,25 @@ public class ConferenceActivity extends ListActivity implements return super.onKeyDown(keyCode, event); } + @Override + public void onAudioStateChanged(final AudioState state) { + mSpeakerButton.post(new Runnable() { + @Override + public void run() { + switch (state) { + case SPEAKER: + mSpeakerButton.setChecked(true); + break; + case EARPIECE: + mSpeakerButton.setChecked(false); + break; + default: + throw new RuntimeException("Unkown audio state " + state); + } + } + }); + } + /* * public int compare(LinphoneCall c1, LinphoneCall c2) { if (c1 == c2) * return 0; diff --git a/src/org/linphone/DialerActivity.java b/src/org/linphone/DialerActivity.java index 0ecfb3767..6bbd2a99d 100644 --- a/src/org/linphone/DialerActivity.java +++ b/src/org/linphone/DialerActivity.java @@ -288,7 +288,7 @@ public class DialerActivity extends Activity implements LinphoneGuiListener, Lin } - private void exitCallMode() { + private void exitCallMode(LinphoneCall call) { if (getResources().getBoolean(R.bool.use_incoming_call_activity)) { finishActivity(INCOMING_CALL_ACTIVITY); } else if (getResources().getBoolean(R.bool.use_incoming_call_dialog)) { @@ -316,7 +316,8 @@ public class DialerActivity extends Activity implements LinphoneGuiListener, Lin mHangup.setEnabled(false); - if (useVideoActivity && LinphoneManager.getLc().isVideoEnabled()) { + if (useVideoActivity && LinphoneManager.getLc().isVideoEnabled() + && VideoCallActivity.call == call) { LinphoneActivity.instance().finishVideoActivity(); BandwidthManager.getInstance().setUserRestriction(false); LinphoneManager.getInstance().resetCameraFromPreferences(); @@ -464,12 +465,12 @@ public class DialerActivity extends Activity implements LinphoneGuiListener, Lin showToast(R.string.call_error, message); if (lc.getCallsNb() == 0){ if (mWakeLock.isHeld()) mWakeLock.release(); - exitCallMode(); + exitCallMode(call); LinphoneActivity.instance().stopOrientationSensor(); } }else if (state==LinphoneCall.State.CallEnd){ if (lc.getCallsNb() == 0){ - exitCallMode(); + exitCallMode(call); LinphoneActivity.instance().stopOrientationSensor(); } } diff --git a/src/org/linphone/LinphoneActivity.java b/src/org/linphone/LinphoneActivity.java index 62c89439e..faad7585a 100644 --- a/src/org/linphone/LinphoneActivity.java +++ b/src/org/linphone/LinphoneActivity.java @@ -256,8 +256,9 @@ public class LinphoneActivity extends TabActivity implements SensorEventListener super.onPause(); if (isFinishing()) { - //restore audio settings - LinphoneManager.getInstance().routeAudioToReceiver(); + //restore audio settings + boolean isUserRequest = false; + LinphoneManager.getInstance().routeAudioToReceiver(isUserRequest); LinphoneManager.stopProximitySensorForActivity(this); instance = null; } @@ -469,7 +470,8 @@ public class LinphoneActivity extends TabActivity implements SensorEventListener video_activity); } }); - LinphoneManager.getInstance().routeAudioToSpeaker(); + boolean isUserRequest = false; + LinphoneManager.getInstance().routeAudioToSpeaker(isUserRequest); } public void startConferenceActivity() { diff --git a/src/org/linphone/LinphoneManager.java b/src/org/linphone/LinphoneManager.java index 941764eb2..067cb43f7 100644 --- a/src/org/linphone/LinphoneManager.java +++ b/src/org/linphone/LinphoneManager.java @@ -46,7 +46,9 @@ import java.util.Set; import java.util.Timer; import java.util.TimerTask; +import org.linphone.LinphoneSimpleListener.LinphoneAudioChangedListener; import org.linphone.LinphoneSimpleListener.LinphoneServiceListener; +import org.linphone.LinphoneSimpleListener.LinphoneAudioChangedListener.AudioState; import org.linphone.core.LinphoneAddress; import org.linphone.core.LinphoneAuthInfo; import org.linphone.core.LinphoneCall; @@ -177,6 +179,12 @@ public final class LinphoneManager implements LinphoneCoreListener { getInstance().routeAudioToSpeakerHelperHelper(speakerOn); } private void routeAudioToSpeakerHelperHelper(boolean speakerOn) { + boolean different = isSpeakerOn() ^ speakerOn; + if (!different) { + Log.d("Skipping change audio route by the same route ", + speakerOn ? "speaker" : "earpiece"); + return; + } if (Hacks.needGalaxySAudioHack() || lpm.useGalaxySHack()) setAudioModeIncallForGalaxyS(); @@ -191,6 +199,9 @@ public final class LinphoneManager implements LinphoneCoreListener { } else { mAudioManager.setSpeakerphoneOn(speakerOn); } + for (LinphoneAudioChangedListener listener : getSimpleListeners(LinphoneAudioChangedListener.class)) { + listener.onAudioStateChanged(speakerOn ? AudioState.SPEAKER : AudioState.EARPIECE); + } } private synchronized void routeAudioToSpeakerHelper(boolean speakerOn) { final LinphoneCall call = mLc.getCurrentCall(); @@ -202,8 +213,24 @@ public final class LinphoneManager implements LinphoneCoreListener { } } - - public void routeAudioToSpeaker() { + private static boolean sUserRequestedSpeaker; + public static final boolean isUserRequestedSpeaker() {return sUserRequestedSpeaker;} + + public void restoreUserRequestedSpeaker() { + if (sUserRequestedSpeaker) { + routeAudioToSpeaker(false); + } else { + routeAudioToReceiver(false); + } + } + /** + * + * @param isUserRequest true if the setting is permanent, otherwise it can be lost + * eg: video activity imply speaker on, which is not a request from the user. + * when the activity stops, the sound is routed to the previously user requested route. + */ + public void routeAudioToSpeaker(boolean isUserRequest) { + if (isUserRequest) sUserRequestedSpeaker = true; routeAudioToSpeakerHelper(true); if (mLc.isIncall()) { /*disable EC, it is not efficient enough on speaker mode due to bad quality of speakers and saturation*/ @@ -214,7 +241,14 @@ public final class LinphoneManager implements LinphoneCoreListener { } - public void routeAudioToReceiver() { + /** + * + * @param isUserRequest true if the setting is permanent, otherwise it can be lost + * eg: video activity imply speaker on, which is not a request from the user. + * when the activity stops, the sound is routed to the previously user requested route. + */ + public void routeAudioToReceiver(boolean isUserRequest) { + if (isUserRequest) sUserRequestedSpeaker = false; routeAudioToSpeakerHelper(false); if (mLc.isIncall()) { //Restore default value @@ -677,7 +711,7 @@ public final class LinphoneManager implements LinphoneCoreListener { void onEcCalibrationStatus(EcCalibratorStatus status, int delayMs); } - private ListenerDispatcher listenerDispatcher = new ListenerDispatcher(simpleListeners); + private ListenerDispatcher listenerDispatcher = new ListenerDispatcher(); private LinphoneCall ringingCall; private MediaPlayer mRingerPlayer; @@ -746,7 +780,6 @@ public final class LinphoneManager implements LinphoneCoreListener { } else if (call == ringingCall && isRinging) { //previous state was ringing, so stop ringing stopRinging(); - routeAudioToReceiver(); } if (state == CallEnd || state == Error) { @@ -853,6 +886,8 @@ public final class LinphoneManager implements LinphoneCoreListener { isRinging = false; // You may need to call galaxys audio hack after this method + boolean isUserRequest = false; + routeAudioToReceiver(isUserRequest); } @@ -1067,21 +1102,17 @@ public final class LinphoneManager implements LinphoneCoreListener { return getLc(); } - private static class ListenerDispatcher implements LinphoneServiceListener { - private LinphoneServiceListener serviceListener; - List simpleListeners; - public ListenerDispatcher(List simpleListeners) { - this.simpleListeners = simpleListeners; // yes, really keeps a reference, not a copy + @SuppressWarnings("unchecked") + private List getSimpleListeners(Class clazz) { + List list = new ArrayList(); + for (LinphoneSimpleListener l : simpleListeners) { + if (clazz.isInstance(l)) list.add((T) l); } + return list; + } - @SuppressWarnings("unchecked") - private List getSimpleListeners(Class clazz) { - List list = new ArrayList(); - for (LinphoneSimpleListener l : simpleListeners) { - if (clazz.isInstance(l)) list.add((T) l); - } - return list; - } + private class ListenerDispatcher implements LinphoneServiceListener { + private LinphoneServiceListener serviceListener; public void setServiceListener(LinphoneServiceListener s) { this.serviceListener = s; @@ -1098,6 +1129,9 @@ public final class LinphoneManager implements LinphoneCoreListener { public void onCallStateChanged(LinphoneCall call, State state, String message) { + if (state == State.CallEnd && mLc.getCallsNb() == 0) { + routeAudioToReceiver(true); + } if (serviceListener != null) serviceListener.onCallStateChanged(call, state, message); for (LinphoneOnCallStateChangedListener l : getSimpleListeners(LinphoneOnCallStateChangedListener.class)) { l.onCallStateChanged(call, state, message); diff --git a/src/org/linphone/LinphoneSimpleListener.java b/src/org/linphone/LinphoneSimpleListener.java index d64b2bb3b..5da9645f4 100644 --- a/src/org/linphone/LinphoneSimpleListener.java +++ b/src/org/linphone/LinphoneSimpleListener.java @@ -47,4 +47,9 @@ public interface LinphoneSimpleListener { public static interface LinphoneOnCallStateChangedListener extends LinphoneSimpleListener { void onCallStateChanged(LinphoneCall call, State state, String message); } + + public static interface LinphoneAudioChangedListener extends LinphoneSimpleListener { + public enum AudioState {EARPIECE, SPEAKER} + void onAudioStateChanged(AudioState state); + } } diff --git a/src/org/linphone/VideoCallActivity.java b/src/org/linphone/VideoCallActivity.java index de45c330c..dc1e32c45 100755 --- a/src/org/linphone/VideoCallActivity.java +++ b/src/org/linphone/VideoCallActivity.java @@ -50,6 +50,7 @@ public class VideoCallActivity extends Activity { private SurfaceView mVideoViewReady; private SurfaceView mVideoCaptureViewReady; public static boolean launched = false; + public static LinphoneCall call; private WakeLock mWakeLock; private Handler refreshHandler = new Handler(); @@ -280,7 +281,10 @@ public class VideoCallActivity extends Activity { @Override protected void onPause() { Log.d("onPause VideoCallActivity (isFinishing:", isFinishing(), ", inCall:", LinphoneManager.getLc().isIncall(), ", changingConf:", getChangingConfigurations()); - + if (isFinishing()) { + call = null; // release reference + } + LinphoneManager.getInstance().restoreUserRequestedSpeaker(); launched=false; synchronized (androidVideoWindowImpl) { /* this call will destroy native opengl renderer diff --git a/src/org/linphone/ui/SpeakerButton.java b/src/org/linphone/ui/SpeakerButton.java index 35d2beb1b..05b53867a 100644 --- a/src/org/linphone/ui/SpeakerButton.java +++ b/src/org/linphone/ui/SpeakerButton.java @@ -48,9 +48,9 @@ public class SpeakerButton extends ToggleImageButton implements OnCheckedChangeL public void onCheckedChanged(ToggleImageButton button, boolean checked) { if (checked) { - LinphoneManager.getInstance().routeAudioToSpeaker(); + LinphoneManager.getInstance().routeAudioToSpeaker(true); } else { - LinphoneManager.getInstance().routeAudioToReceiver(); + LinphoneManager.getInstance().routeAudioToReceiver(true); } }