diff --git a/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java b/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java index ba22604e4..4c4a35d0c 100644 --- a/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java @@ -410,12 +410,16 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe @SuppressLint("RestrictedApi") private void updateInCallButtonConfiguration(final RtpEndUserState state) { if (state == RtpEndUserState.CONNECTED) { - final AppRTCAudioManager audioManager = requireRtpConnection().getAudioManager(); - updateInCallButtonConfiguration( - audioManager.getSelectedAudioDevice(), - audioManager.getAudioDevices().size(), - requireRtpConnection().isMicrophoneEnabled() - ); + if (getMedia().contains(Media.VIDEO)) { + updateInCallButtonConfigurationVideo(requireRtpConnection().isVideoEnabled()); + } else { + final AppRTCAudioManager audioManager = requireRtpConnection().getAudioManager(); + updateInCallButtonConfigurationSpeaker( + audioManager.getSelectedAudioDevice(), + audioManager.getAudioDevices().size() + ); + } + updateInCallButtonConfigurationMicrophone(requireRtpConnection().isMicrophoneEnabled()); } else { this.binding.inCallActionLeft.setVisibility(View.GONE); this.binding.inCallActionRight.setVisibility(View.GONE); @@ -423,48 +427,75 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe } @SuppressLint("RestrictedApi") - private void updateInCallButtonConfiguration(final AppRTCAudioManager.AudioDevice selectedAudioDevice, final int numberOfChoices, final boolean microphoneEnabled) { + private void updateInCallButtonConfigurationSpeaker(final AppRTCAudioManager.AudioDevice selectedAudioDevice, final int numberOfChoices) { switch (selectedAudioDevice) { case EARPIECE: - this.binding.inCallActionLeft.setImageResource(R.drawable.ic_volume_off_black_24dp); + this.binding.inCallActionRight.setImageResource(R.drawable.ic_volume_off_black_24dp); if (numberOfChoices >= 2) { - this.binding.inCallActionLeft.setOnClickListener(this::switchToSpeaker); + this.binding.inCallActionRight.setOnClickListener(this::switchToSpeaker); } else { - this.binding.inCallActionLeft.setOnClickListener(null); - this.binding.inCallActionLeft.setClickable(false); + this.binding.inCallActionRight.setOnClickListener(null); + this.binding.inCallActionRight.setClickable(false); } break; case WIRED_HEADSET: - this.binding.inCallActionLeft.setImageResource(R.drawable.ic_headset_black_24dp); - this.binding.inCallActionLeft.setOnClickListener(null); - this.binding.inCallActionLeft.setClickable(false); + this.binding.inCallActionRight.setImageResource(R.drawable.ic_headset_black_24dp); + this.binding.inCallActionRight.setOnClickListener(null); + this.binding.inCallActionRight.setClickable(false); break; case SPEAKER_PHONE: - this.binding.inCallActionLeft.setImageResource(R.drawable.ic_volume_up_black_24dp); + this.binding.inCallActionRight.setImageResource(R.drawable.ic_volume_up_black_24dp); if (numberOfChoices >= 2) { - this.binding.inCallActionLeft.setOnClickListener(this::switchToEarpiece); + this.binding.inCallActionRight.setOnClickListener(this::switchToEarpiece); } else { - this.binding.inCallActionLeft.setOnClickListener(null); - this.binding.inCallActionLeft.setClickable(false); + this.binding.inCallActionRight.setOnClickListener(null); + this.binding.inCallActionRight.setClickable(false); } break; case BLUETOOTH: - this.binding.inCallActionLeft.setImageResource(R.drawable.ic_bluetooth_audio_black_24dp); - this.binding.inCallActionLeft.setOnClickListener(null); - this.binding.inCallActionLeft.setClickable(false); + this.binding.inCallActionRight.setImageResource(R.drawable.ic_bluetooth_audio_black_24dp); + this.binding.inCallActionRight.setOnClickListener(null); + this.binding.inCallActionRight.setClickable(false); break; } - this.binding.inCallActionLeft.setVisibility(View.VISIBLE); - if (microphoneEnabled) { - this.binding.inCallActionRight.setImageResource(R.drawable.ic_mic_black_24dp); - this.binding.inCallActionRight.setOnClickListener(this::disableMicrophone); - } else { - this.binding.inCallActionRight.setImageResource(R.drawable.ic_mic_off_black_24dp); - this.binding.inCallActionRight.setOnClickListener(this::enableMicrophone); - } this.binding.inCallActionRight.setVisibility(View.VISIBLE); } + @SuppressLint("RestrictedApi") + private void updateInCallButtonConfigurationVideo(final boolean videoEnabled) { + this.binding.inCallActionRight.setVisibility(View.VISIBLE); + if (videoEnabled) { + this.binding.inCallActionRight.setImageResource(R.drawable.ic_videocam_black_24dp); + this.binding.inCallActionRight.setOnClickListener(this::disableVideo); + } else { + this.binding.inCallActionRight.setImageResource(R.drawable.ic_videocam_off_black_24dp); + this.binding.inCallActionRight.setOnClickListener(this::enableVideo); + } + } + + private void enableVideo(View view) { + requireRtpConnection().setVideoEnabled(true); + updateInCallButtonConfigurationVideo(true); + } + + private void disableVideo(View view) { + requireRtpConnection().setVideoEnabled(false); + updateInCallButtonConfigurationVideo(false); + + } + + @SuppressLint("RestrictedApi") + private void updateInCallButtonConfigurationMicrophone(final boolean microphoneEnabled) { + if (microphoneEnabled) { + this.binding.inCallActionLeft.setImageResource(R.drawable.ic_mic_black_24dp); + this.binding.inCallActionLeft.setOnClickListener(this::disableMicrophone); + } else { + this.binding.inCallActionLeft.setImageResource(R.drawable.ic_mic_off_black_24dp); + this.binding.inCallActionLeft.setOnClickListener(this::enableMicrophone); + } + this.binding.inCallActionLeft.setVisibility(View.VISIBLE); + } + private void updateVideoViews() { final Optional localVideoTrack = requireRtpConnection().geLocalVideoTrack(); if (localVideoTrack.isPresent()) { @@ -572,12 +603,11 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe public void onAudioDeviceChanged(AppRTCAudioManager.AudioDevice selectedAudioDevice, Set availableAudioDevices) { Log.d(Config.LOGTAG, "onAudioDeviceChanged in activity: selected:" + selectedAudioDevice + ", available:" + availableAudioDevices); try { - if (requireRtpConnection().getEndUserState() == RtpEndUserState.CONNECTED) { + if (requireRtpConnection().getEndUserState() == RtpEndUserState.CONNECTED && !getMedia().contains(Media.VIDEO)) { final AppRTCAudioManager audioManager = requireRtpConnection().getAudioManager(); - updateInCallButtonConfiguration( + updateInCallButtonConfigurationSpeaker( audioManager.getSelectedAudioDevice(), - audioManager.getAudioDevices().size(), - requireRtpConnection().isMicrophoneEnabled() + audioManager.getAudioDevices().size() ); } putProximityWakeLockInProperState(); diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java index 317dd7cf0..976e3ad3e 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -930,6 +930,14 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web webRTCWrapper.setMicrophoneEnabled(enabled); } + public boolean isVideoEnabled() { + return webRTCWrapper.isVideoEnabled(); + } + + public void setVideoEnabled(final boolean enabled) { + webRTCWrapper.setVideoEnabled(enabled); + } + @Override public void onAudioDeviceChanged(AppRTCAudioManager.AudioDevice selectedAudioDevice, Set availableAudioDevices) { xmppConnectionService.notifyJingleRtpConnectionUpdate(selectedAudioDevice, availableAudioDevices); diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java index 8e87291cd..70c4f8e7b 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java @@ -228,7 +228,7 @@ public class WebRTCWrapper { } } - public boolean isMicrophoneEnabled() { + boolean isMicrophoneEnabled() { final AudioTrack audioTrack = this.localAudioTrack; if (audioTrack == null) { throw new IllegalStateException("Local audio track does not exist (yet)"); @@ -236,7 +236,7 @@ public class WebRTCWrapper { return audioTrack.enabled(); } - public void setMicrophoneEnabled(final boolean enabled) { + void setMicrophoneEnabled(final boolean enabled) { final AudioTrack audioTrack = this.localAudioTrack; if (audioTrack == null) { throw new IllegalStateException("Local audio track does not exist (yet)"); @@ -244,6 +244,22 @@ public class WebRTCWrapper { audioTrack.setEnabled(enabled); } + public boolean isVideoEnabled() { + final VideoTrack videoTrack = this.localVideoTrack; + if (videoTrack == null) { + throw new IllegalStateException("Local video track does not exist"); + } + return videoTrack.enabled(); + } + + public void setVideoEnabled(final boolean enabled) { + final VideoTrack videoTrack = this.localVideoTrack; + if (videoTrack == null) { + throw new IllegalStateException("Local video track does not exist"); + } + videoTrack.setEnabled(enabled); + } + public ListenableFuture createOffer() { return Futures.transformAsync(getPeerConnectionFuture(), peerConnection -> { final SettableFuture future = SettableFuture.create(); diff --git a/src/main/res/drawable-hdpi/ic_videocam_off_black_24dp.png b/src/main/res/drawable-hdpi/ic_videocam_off_black_24dp.png new file mode 100644 index 000000000..06140f119 Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_videocam_off_black_24dp.png differ diff --git a/src/main/res/drawable-mdpi/ic_videocam_off_black_24dp.png b/src/main/res/drawable-mdpi/ic_videocam_off_black_24dp.png new file mode 100644 index 000000000..c71d75ceb Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_videocam_off_black_24dp.png differ diff --git a/src/main/res/drawable-xhdpi/ic_videocam_off_black_24dp.png b/src/main/res/drawable-xhdpi/ic_videocam_off_black_24dp.png new file mode 100644 index 000000000..2ffb7c5d5 Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_videocam_off_black_24dp.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_videocam_off_black_24dp.png b/src/main/res/drawable-xxhdpi/ic_videocam_off_black_24dp.png new file mode 100644 index 000000000..32d61d8df Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_videocam_off_black_24dp.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_videocam_off_black_24dp.png b/src/main/res/drawable-xxxhdpi/ic_videocam_off_black_24dp.png new file mode 100644 index 000000000..2a86702f8 Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_videocam_off_black_24dp.png differ