From d09a6714afe30687daae06ac19e32ac95b25b57c Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 7 Jan 2021 11:17:23 +0100 Subject: [PATCH] VoIP: use DialPad bottom sheet to send Dtmf in call --- .../features/call/CallControlsBottomSheet.kt | 5 +++++ .../app/features/call/VectorCallActivity.kt | 19 +++++++++++++++++-- .../features/call/VectorCallViewActions.kt | 3 +++ .../app/features/call/VectorCallViewEvents.kt | 1 + .../app/features/call/VectorCallViewModel.kt | 6 ++++++ .../app/features/call/webrtc/WebRtcCall.kt | 17 +++++++++++++++++ .../main/res/drawable/ic_call_dial_pad.xml | 9 +++++++++ .../res/layout/bottom_sheet_call_controls.xml | 11 +++++++++++ 8 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 vector/src/main/res/drawable/ic_call_dial_pad.xml diff --git a/vector/src/main/java/im/vector/app/features/call/CallControlsBottomSheet.kt b/vector/src/main/java/im/vector/app/features/call/CallControlsBottomSheet.kt index a94a030e34..29aa72b11f 100644 --- a/vector/src/main/java/im/vector/app/features/call/CallControlsBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/call/CallControlsBottomSheet.kt @@ -63,6 +63,11 @@ class CallControlsBottomSheet : VectorBaseBottomSheetDialogFragment { diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt index c9a078e260..0e560dbdb1 100644 --- a/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt +++ b/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt @@ -43,6 +43,8 @@ import im.vector.app.core.utils.PERMISSIONS_FOR_VIDEO_IP_CALL import im.vector.app.core.utils.allGranted import im.vector.app.core.utils.checkPermissions import im.vector.app.databinding.ActivityCallBinding +import im.vector.app.features.call.dialpad.CallDialPadBottomSheet +import im.vector.app.features.call.dialpad.DialPadFragment import im.vector.app.features.call.utils.EglUtils import im.vector.app.features.call.webrtc.WebRtcCallManager import im.vector.app.features.home.AvatarRenderer @@ -83,9 +85,14 @@ class VectorCallActivity : VectorBaseActivity(), CallContro private lateinit var callArgs: CallArgs @Inject lateinit var callManager: WebRtcCallManager - @Inject lateinit var viewModelFactory: VectorCallViewModel.Factory + private val dialPadCallback = object : DialPadFragment.Callback { + override fun onDigitAppended(digit: String) { + callViewModel.handle(VectorCallViewActions.SendDtmfDigit(digit)) + } + } + private var rootEglBase: EglBase? = null var surfaceRenderersAreInitialized = false @@ -114,7 +121,9 @@ class VectorCallActivity : VectorBaseActivity(), CallContro if (intent.getStringExtra(EXTRA_MODE) == INCOMING_RINGING) { turnScreenOnAndKeyguardOff() } - + if(savedInstanceState != null) { + (supportFragmentManager.findFragmentByTag(FRAGMENT_DIAL_PAD_TAG) as? CallDialPadBottomSheet)?.callback = dialPadCallback + } configureCallViews() callViewModel.subscribe(this) { @@ -301,6 +310,11 @@ class VectorCallActivity : VectorBaseActivity(), CallContro is VectorCallViewEvents.ConnectionTimeout -> { onErrorTimoutConnect(event.turn) } + is VectorCallViewEvents.ShowDialPad -> { + CallDialPadBottomSheet.newInstance(false).apply { + callback = dialPadCallback + }.show(supportFragmentManager, FRAGMENT_DIAL_PAD_TAG) + } null -> { } } @@ -323,6 +337,7 @@ class VectorCallActivity : VectorBaseActivity(), CallContro private const val CAPTURE_PERMISSION_REQUEST_CODE = 1 private const val EXTRA_MODE = "EXTRA_MODE" + private const val FRAGMENT_DIAL_PAD_TAG = "FRAGMENT_DIAL_PAD_TAG" const val OUTGOING_CREATED = "OUTGOING_CREATED" const val INCOMING_RINGING = "INCOMING_RINGING" diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallViewActions.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallViewActions.kt index 83ac878186..05e4ed4d0a 100644 --- a/vector/src/main/java/im/vector/app/features/call/VectorCallViewActions.kt +++ b/vector/src/main/java/im/vector/app/features/call/VectorCallViewActions.kt @@ -25,7 +25,10 @@ sealed class VectorCallViewActions : VectorViewModelAction { object ToggleMute : VectorCallViewActions() object ToggleVideo : VectorCallViewActions() object ToggleHoldResume: VectorCallViewActions() + object OpenDialPad: VectorCallViewActions() data class ChangeAudioDevice(val device: CallAudioManager.SoundDevice) : VectorCallViewActions() + data class SendDtmfDigit(val digit: String) : VectorCallViewActions() + object SwitchSoundDevice : VectorCallViewActions() object HeadSetButtonPressed : VectorCallViewActions() object ToggleCamera : VectorCallViewActions() diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallViewEvents.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallViewEvents.kt index b79cd5d772..a376e08983 100644 --- a/vector/src/main/java/im/vector/app/features/call/VectorCallViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/call/VectorCallViewEvents.kt @@ -27,6 +27,7 @@ sealed class VectorCallViewEvents : VectorViewEvents { val available: List, val current: CallAudioManager.SoundDevice ) : VectorCallViewEvents() + object ShowDialPad: VectorCallViewEvents() // data class CallAnswered(val content: CallAnswerContent) : VectorCallViewEvents() // data class CallHangup(val content: CallHangupContent) : VectorCallViewEvents() // object CallAccepted : VectorCallViewEvents() diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt index e1a01bbaa3..424f54b1bf 100644 --- a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt @@ -246,6 +246,12 @@ class VectorCallViewModel @AssistedInject constructor( if (!state.isVideoCall) return@withState call?.setCaptureFormat(if (state.isHD) CaptureFormat.SD else CaptureFormat.HD) } + VectorCallViewActions.OpenDialPad -> { + _viewEvents.post(VectorCallViewEvents.ShowDialPad) + } + is VectorCallViewActions.SendDtmfDigit -> { + call?.sendDtmfDigit(action.digit) + } }.exhaustive } diff --git a/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCall.kt b/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCall.kt index 10c7cb2e24..745e6a24c3 100644 --- a/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCall.kt +++ b/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCall.kt @@ -273,6 +273,23 @@ class WebRtcCall(val mxCall: MxCall, } } + /** + * Sends a DTMF digit to the other party + * @param digit The digit (nb. string - '#' and '*' are dtmf too) + */ + fun sendDtmfDigit(digit: String) { + for (sender in peerConnection?.senders.orEmpty()) { + if (sender.track()?.kind() == "audio" && sender.dtmf()?.canInsertDtmf() == true) { + try { + sender.dtmf()?.insertDtmf(digit, 100, 70) + return + } catch (failure: Throwable) { + Timber.v("Fail to send Dtmf digit") + } + } + } + } + fun detachRenderers(renderers: List?) { Timber.v("## VOIP detachRenderers") // currentCall?.localMediaStream?.let { currentCall?.peerConnection?.removeStream(it) } diff --git a/vector/src/main/res/drawable/ic_call_dial_pad.xml b/vector/src/main/res/drawable/ic_call_dial_pad.xml new file mode 100644 index 0000000000..a917d592bc --- /dev/null +++ b/vector/src/main/res/drawable/ic_call_dial_pad.xml @@ -0,0 +1,9 @@ + + + diff --git a/vector/src/main/res/layout/bottom_sheet_call_controls.xml b/vector/src/main/res/layout/bottom_sheet_call_controls.xml index b8a532e89d..bd6e939ff1 100644 --- a/vector/src/main/res/layout/bottom_sheet_call_controls.xml +++ b/vector/src/main/res/layout/bottom_sheet_call_controls.xml @@ -26,6 +26,15 @@ app:tint="?attr/riotx_text_primary" tools:actionDescription="Front" /> + + + +