Signal-Android/src/org/thoughtcrime/securesms/components/webrtc/WebRtcInCallAudioButton.java

190 lines
6.0 KiB
Java

package org.thoughtcrime.securesms.components.webrtc;
import android.content.Context;
import android.graphics.drawable.LayerDrawable;
import android.support.v7.widget.PopupMenu;
import android.util.Log;
import android.view.MenuItem;
import android.widget.CompoundButton;
import org.thoughtcrime.redphone.util.AudioUtils;
import org.thoughtcrime.securesms.R;
import static org.thoughtcrime.redphone.util.AudioUtils.AudioMode.DEFAULT;
import static org.thoughtcrime.redphone.util.AudioUtils.AudioMode.HEADSET;
import static org.thoughtcrime.redphone.util.AudioUtils.AudioMode.SPEAKER;
/**
* Manages the audio button displayed on the in-call screen
*
* The behavior of this button depends on the availability of headset audio, and changes from being a regular
* toggle button (enabling speakerphone) to bringing up a model dialog that includes speakerphone, bluetooth,
* and regular audio options.
*
* Based on com.android.phone.InCallTouchUI
*
* @author Stuart O. Anderson
*/
public class WebRtcInCallAudioButton {
private static final String TAG = WebRtcInCallAudioButton.class.getName();
private final CompoundButton mAudioButton;
private boolean headsetAvailable;
private AudioUtils.AudioMode currentMode;
private Context context;
private WebRtcCallControls.AudioButtonListener listener;
public WebRtcInCallAudioButton(CompoundButton audioButton) {
mAudioButton = audioButton;
currentMode = DEFAULT;
headsetAvailable = false;
updateView();
setListener(new WebRtcCallControls.AudioButtonListener() {
@Override
public void onAudioChange(AudioUtils.AudioMode mode) {
//No Action By Default.
}
});
context = audioButton.getContext();
}
public void setHeadsetAvailable(boolean available) {
headsetAvailable = available;
updateView();
}
public void setAudioMode(AudioUtils.AudioMode newMode) {
currentMode = newMode;
updateView();
}
private void updateView() {
// The various layers of artwork for this button come from
// redphone_btn_compound_audio.xmlaudio.xml. Keep track of which layers we want to be
// visible:
//
// - This selector shows the blue bar below the button icon when
// this button is a toggle *and* it's currently "checked".
boolean showToggleStateIndication = false;
//
// - This is visible if the popup menu is enabled:
boolean showMoreIndicator = false;
//
// - Foreground icons for the button. Exactly one of these is enabled:
boolean showSpeakerOnIcon = false;
// boolean showSpeakerOffIcon = false;
boolean showHandsetIcon = false;
boolean showHeadsetIcon = false;
boolean speakerOn = currentMode == AudioUtils.AudioMode.SPEAKER;
if (headsetAvailable) {
mAudioButton.setEnabled(true);
// The audio button is NOT a toggle in this state. (And its
// setChecked() state is irrelevant since we completely hide the
// redphone_btn_compound_background layer anyway.)
// Update desired layers:
showMoreIndicator = true;
Log.d(TAG, "UI Mode: " + currentMode);
if (currentMode == AudioUtils.AudioMode.HEADSET) {
showHeadsetIcon = true;
} else if (speakerOn) {
showSpeakerOnIcon = true;
} else {
showHandsetIcon = true;
}
} else {
mAudioButton.setEnabled(true);
mAudioButton.setChecked(speakerOn);
showSpeakerOnIcon = true;
// showSpeakerOnIcon = speakerOn;
// showSpeakerOffIcon = !speakerOn;
showToggleStateIndication = true;
}
final int HIDDEN = 0;
final int VISIBLE = 255;
LayerDrawable layers = (LayerDrawable) mAudioButton.getBackground();
layers.findDrawableByLayerId(R.id.compoundBackgroundItem)
.setAlpha(showToggleStateIndication ? VISIBLE : HIDDEN);
layers.findDrawableByLayerId(R.id.moreIndicatorItem)
.setAlpha(showMoreIndicator ? VISIBLE : HIDDEN);
layers.findDrawableByLayerId(R.id.bluetoothItem)
.setAlpha(showHeadsetIcon ? VISIBLE : HIDDEN);
layers.findDrawableByLayerId(R.id.handsetItem)
.setAlpha(showHandsetIcon ? VISIBLE : HIDDEN);
layers.findDrawableByLayerId(R.id.speakerphoneOnItem)
.setAlpha(showSpeakerOnIcon ? VISIBLE : HIDDEN);
// layers.findDrawableByLayerId(R.id.speakerphoneOffItem)
// .setAlpha(showSpeakerOffIcon ? VISIBLE : HIDDEN);
mAudioButton.invalidate();
}
private void log(String msg) {
Log.d(TAG, msg);
}
public void setListener(final WebRtcCallControls.AudioButtonListener listener) {
this.listener = listener;
mAudioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(headsetAvailable) {
displayAudioChoiceDialog();
} else {
currentMode = b ? AudioUtils.AudioMode.SPEAKER : DEFAULT;
listener.onAudioChange(currentMode);
updateView();
}
}
});
}
private void displayAudioChoiceDialog() {
Log.w(TAG, "Displaying popup...");
PopupMenu popupMenu = new PopupMenu(context, mAudioButton);
popupMenu.getMenuInflater().inflate(R.menu.redphone_audio_popup_menu, popupMenu.getMenu());
popupMenu.setOnMenuItemClickListener(new AudioRoutingPopupListener());
popupMenu.show();
}
private class AudioRoutingPopupListener implements PopupMenu.OnMenuItemClickListener {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.handset:
currentMode = DEFAULT;
break;
case R.id.headset:
currentMode = HEADSET;
break;
case R.id.speaker:
currentMode = SPEAKER;
break;
default:
Log.w(TAG, "Unknown item selected in audio popup menu: " + item.toString());
}
Log.d(TAG, "Selected: " + currentMode + " -- " + item.getItemId());
listener.onAudioChange(currentMode);
updateView();
return true;
}
}
}