make mute and speaker button work
@ -16,6 +16,7 @@ import android.view.View;
 | 
				
			|||||||
import android.view.WindowManager;
 | 
					import android.view.WindowManager;
 | 
				
			||||||
import android.widget.Toast;
 | 
					import android.widget.Toast;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.google.common.base.Preconditions;
 | 
				
			||||||
import com.google.common.collect.ImmutableList;
 | 
					import com.google.common.collect.ImmutableList;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.lang.ref.WeakReference;
 | 
					import java.lang.ref.WeakReference;
 | 
				
			||||||
@ -344,18 +345,91 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
 | 
				
			|||||||
            this.binding.endCall.setVisibility(View.VISIBLE);
 | 
					            this.binding.endCall.setVisibility(View.VISIBLE);
 | 
				
			||||||
            this.binding.acceptCall.setVisibility(View.INVISIBLE);
 | 
					            this.binding.acceptCall.setVisibility(View.INVISIBLE);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        updateInCallButtonConfiguration(state);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void updateInCallButtonConfiguration() {
 | 
				
			||||||
 | 
					        updateInCallButtonConfiguration(requireRtpConnection().getEndUserState());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @SuppressLint("RestrictedApi")
 | 
				
			||||||
 | 
					    private void updateInCallButtonConfiguration(final RtpEndUserState state) {
 | 
				
			||||||
        if (state == RtpEndUserState.CONNECTED) {
 | 
					        if (state == RtpEndUserState.CONNECTED) {
 | 
				
			||||||
            this.binding.inCallActionLeft.setImageResource(R.drawable.ic_volume_off_black_24dp);
 | 
					            final AppRTCAudioManager audioManager = requireRtpConnection().getAudioManager();
 | 
				
			||||||
            this.binding.inCallActionLeft.setVisibility(View.VISIBLE);
 | 
					            updateInCallButtonConfiguration(
 | 
				
			||||||
            this.binding.inCallActionRight.setImageResource(R.drawable.ic_mic_black_24dp);
 | 
					                    audioManager.getSelectedAudioDevice(),
 | 
				
			||||||
            this.binding.inCallActionRight.setVisibility(View.VISIBLE);
 | 
					                    audioManager.getAudioDevices().size(),
 | 
				
			||||||
 | 
					                    requireRtpConnection().isMicrophoneEnabled()
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            this.binding.inCallActionLeft.setVisibility(View.GONE);
 | 
					            this.binding.inCallActionLeft.setVisibility(View.GONE);
 | 
				
			||||||
            this.binding.inCallActionRight.setVisibility(View.GONE);
 | 
					            this.binding.inCallActionRight.setVisibility(View.GONE);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @SuppressLint("RestrictedApi")
 | 
				
			||||||
 | 
					    private void updateInCallButtonConfiguration(final AppRTCAudioManager.AudioDevice selectedAudioDevice, final int numberOfChoices, final boolean microphoneEnabled) {
 | 
				
			||||||
 | 
					        switch (selectedAudioDevice) {
 | 
				
			||||||
 | 
					            case EARPIECE:
 | 
				
			||||||
 | 
					                this.binding.inCallActionLeft.setImageResource(R.drawable.ic_volume_off_black_24dp);
 | 
				
			||||||
 | 
					                if (numberOfChoices >= 2) {
 | 
				
			||||||
 | 
					                    this.binding.inCallActionLeft.setOnClickListener(this::switchToSpeaker);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    this.binding.inCallActionLeft.setOnClickListener(null);
 | 
				
			||||||
 | 
					                    this.binding.inCallActionLeft.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);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case SPEAKER_PHONE:
 | 
				
			||||||
 | 
					                this.binding.inCallActionLeft.setImageResource(R.drawable.ic_volume_up_black_24dp);
 | 
				
			||||||
 | 
					                if (numberOfChoices >= 2) {
 | 
				
			||||||
 | 
					                    this.binding.inCallActionLeft.setOnClickListener(this::switchToEarpiece);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    this.binding.inCallActionLeft.setOnClickListener(null);
 | 
				
			||||||
 | 
					                    this.binding.inCallActionLeft.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);
 | 
				
			||||||
 | 
					                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);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void disableMicrophone(View view) {
 | 
				
			||||||
 | 
					        JingleRtpConnection rtpConnection = requireRtpConnection();
 | 
				
			||||||
 | 
					        rtpConnection.setMicrophoneEnabled(false);
 | 
				
			||||||
 | 
					        updateInCallButtonConfiguration();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void enableMicrophone(View view) {
 | 
				
			||||||
 | 
					        JingleRtpConnection rtpConnection = requireRtpConnection();
 | 
				
			||||||
 | 
					        rtpConnection.setMicrophoneEnabled(true);
 | 
				
			||||||
 | 
					        updateInCallButtonConfiguration();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void switchToEarpiece(View view) {
 | 
				
			||||||
 | 
					        requireRtpConnection().getAudioManager().setDefaultAudioDevice(AppRTCAudioManager.AudioDevice.EARPIECE);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void switchToSpeaker(View view) {
 | 
				
			||||||
 | 
					        requireRtpConnection().getAudioManager().setDefaultAudioDevice(AppRTCAudioManager.AudioDevice.SPEAKER_PHONE);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void retry(View view) {
 | 
					    private void retry(View view) {
 | 
				
			||||||
        Log.d(Config.LOGTAG, "attempting retry");
 | 
					        Log.d(Config.LOGTAG, "attempting retry");
 | 
				
			||||||
        final Intent intent = getIntent();
 | 
					        final Intent intent = getIntent();
 | 
				
			||||||
@ -419,6 +493,18 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
 | 
				
			|||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void onAudioDeviceChanged(AppRTCAudioManager.AudioDevice selectedAudioDevice, Set<AppRTCAudioManager.AudioDevice> availableAudioDevices) {
 | 
					    public void onAudioDeviceChanged(AppRTCAudioManager.AudioDevice selectedAudioDevice, Set<AppRTCAudioManager.AudioDevice> availableAudioDevices) {
 | 
				
			||||||
        Log.d(Config.LOGTAG, "onAudioDeviceChanged in activity: selected:" + selectedAudioDevice + ", available:" + availableAudioDevices);
 | 
					        Log.d(Config.LOGTAG, "onAudioDeviceChanged in activity: selected:" + selectedAudioDevice + ", available:" + availableAudioDevices);
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            if (requireRtpConnection().getEndUserState() == RtpEndUserState.CONNECTED) {
 | 
				
			||||||
 | 
					                final AppRTCAudioManager audioManager = requireRtpConnection().getAudioManager();
 | 
				
			||||||
 | 
					                updateInCallButtonConfiguration(
 | 
				
			||||||
 | 
					                        audioManager.getSelectedAudioDevice(),
 | 
				
			||||||
 | 
					                        audioManager.getAudioDevices().size(),
 | 
				
			||||||
 | 
					                        requireRtpConnection().isMicrophoneEnabled()
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (IllegalStateException e) {
 | 
				
			||||||
 | 
					            Log.d(Config.LOGTAG, "RTP connection was not available when audio device changed");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void updateRtpSessionProposalState(final Account account, final Jid with, final RtpEndUserState state) {
 | 
					    private void updateRtpSessionProposalState(final Account account, final Jid with, final RtpEndUserState state) {
 | 
				
			||||||
 | 
				
			|||||||
@ -833,6 +833,18 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public AppRTCAudioManager getAudioManager() {
 | 
				
			||||||
 | 
					        return webRTCWrapper.getAudioManager();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void setMicrophoneEnabled(final boolean enabled) {
 | 
				
			||||||
 | 
					        webRTCWrapper.setMicrophoneEnabled(enabled);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public boolean isMicrophoneEnabled() {
 | 
				
			||||||
 | 
					        return webRTCWrapper.isMicrophoneEnabled();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void onAudioDeviceChanged(AppRTCAudioManager.AudioDevice selectedAudioDevice, Set<AppRTCAudioManager.AudioDevice> availableAudioDevices) {
 | 
					    public void onAudioDeviceChanged(AppRTCAudioManager.AudioDevice selectedAudioDevice, Set<AppRTCAudioManager.AudioDevice> availableAudioDevices) {
 | 
				
			||||||
        xmppConnectionService.notifyJingleRtpConnectionUpdate(selectedAudioDevice, availableAudioDevices);
 | 
					        xmppConnectionService.notifyJingleRtpConnectionUpdate(selectedAudioDevice, availableAudioDevices);
 | 
				
			||||||
 | 
				
			|||||||
@ -131,6 +131,7 @@ public class WebRTCWrapper {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
    @Nullable
 | 
					    @Nullable
 | 
				
			||||||
    private PeerConnection peerConnection = null;
 | 
					    private PeerConnection peerConnection = null;
 | 
				
			||||||
 | 
					    private AudioTrack localAudioTrack = null;
 | 
				
			||||||
    private AppRTCAudioManager appRTCAudioManager = null;
 | 
					    private AppRTCAudioManager appRTCAudioManager = null;
 | 
				
			||||||
    private final Handler mainHandler = new Handler(Looper.getMainLooper());
 | 
					    private final Handler mainHandler = new Handler(Looper.getMainLooper());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -201,10 +202,9 @@ public class WebRTCWrapper {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        final AudioSource audioSource = peerConnectionFactory.createAudioSource(new MediaConstraints());
 | 
					        final AudioSource audioSource = peerConnectionFactory.createAudioSource(new MediaConstraints());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final AudioTrack audioTrack = peerConnectionFactory.createAudioTrack("my-audio-track", audioSource);
 | 
					        this.localAudioTrack = peerConnectionFactory.createAudioTrack("my-audio-track", audioSource);
 | 
				
			||||||
        Log.d(Config.LOGTAG, "audioTrack enabled:" + audioTrack.enabled() + " state=" + audioTrack.state());
 | 
					 | 
				
			||||||
        final MediaStream stream = peerConnectionFactory.createLocalMediaStream("my-media-stream");
 | 
					        final MediaStream stream = peerConnectionFactory.createLocalMediaStream("my-media-stream");
 | 
				
			||||||
        stream.addTrack(audioTrack);
 | 
					        stream.addTrack(this.localAudioTrack);
 | 
				
			||||||
        //stream.addTrack(videoTrack);
 | 
					        //stream.addTrack(videoTrack);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.localVideoTrack = videoTrack;
 | 
					        this.localVideoTrack = videoTrack;
 | 
				
			||||||
@ -229,6 +229,22 @@ public class WebRTCWrapper {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void setMicrophoneEnabled(final boolean enabled) {
 | 
				
			||||||
 | 
					        final AudioTrack audioTrack = this.localAudioTrack;
 | 
				
			||||||
 | 
					        if (audioTrack == null) {
 | 
				
			||||||
 | 
					            throw new IllegalStateException("Local audio track does not exist (yet)");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        audioTrack.setEnabled(enabled);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public boolean isMicrophoneEnabled() {
 | 
				
			||||||
 | 
					        final AudioTrack audioTrack = this.localAudioTrack;
 | 
				
			||||||
 | 
					        if (audioTrack == null) {
 | 
				
			||||||
 | 
					            throw new IllegalStateException("Local audio track does not exist (yet)");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return audioTrack.enabled();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public ListenableFuture<SessionDescription> createOffer() {
 | 
					    public ListenableFuture<SessionDescription> createOffer() {
 | 
				
			||||||
        return Futures.transformAsync(getPeerConnectionFuture(), peerConnection -> {
 | 
					        return Futures.transformAsync(getPeerConnectionFuture(), peerConnection -> {
 | 
				
			||||||
@ -330,6 +346,10 @@ public class WebRTCWrapper {
 | 
				
			|||||||
        return peerConnection;
 | 
					        return peerConnection;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public AppRTCAudioManager getAudioManager() {
 | 
				
			||||||
 | 
					        return appRTCAudioManager;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static abstract class SetSdpObserver implements SdpObserver {
 | 
					    private static abstract class SetSdpObserver implements SdpObserver {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @Override
 | 
					        @Override
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								src/main/res/drawable-hdpi/ic_bluetooth_audio_black_24dp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 420 B  | 
							
								
								
									
										
											BIN
										
									
								
								src/main/res/drawable-hdpi/ic_headset_black_24dp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 349 B  | 
							
								
								
									
										
											BIN
										
									
								
								src/main/res/drawable-mdpi/ic_bluetooth_audio_black_24dp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 283 B  | 
							
								
								
									
										
											BIN
										
									
								
								src/main/res/drawable-mdpi/ic_headset_black_24dp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 230 B  | 
							
								
								
									
										
											BIN
										
									
								
								src/main/res/drawable-xhdpi/ic_bluetooth_audio_black_24dp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 479 B  | 
							
								
								
									
										
											BIN
										
									
								
								src/main/res/drawable-xhdpi/ic_headset_black_24dp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 412 B  | 
							
								
								
									
										
											BIN
										
									
								
								src/main/res/drawable-xxhdpi/ic_bluetooth_audio_black_24dp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 724 B  | 
							
								
								
									
										
											BIN
										
									
								
								src/main/res/drawable-xxhdpi/ic_headset_black_24dp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 586 B  | 
							
								
								
									
										
											BIN
										
									
								
								src/main/res/drawable-xxxhdpi/ic_bluetooth_audio_black_24dp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 867 B  | 
							
								
								
									
										
											BIN
										
									
								
								src/main/res/drawable-xxxhdpi/ic_headset_black_24dp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 786 B  |