Fixes for self-mute during remote conference + rework how we mute single call
This commit is contained in:
parent
18f36b85bb
commit
d6f83f0057
7 changed files with 78 additions and 51 deletions
|
@ -83,26 +83,6 @@ class CallActivity : ProximitySensorActivity() {
|
||||||
|
|
||||||
statsViewModel = ViewModelProvider(navControllerStoreOwner)[StatisticsListViewModel::class.java]
|
statsViewModel = ViewModelProvider(navControllerStoreOwner)[StatisticsListViewModel::class.java]
|
||||||
|
|
||||||
callsViewModel.noMoreCallEvent.observe(
|
|
||||||
this
|
|
||||||
) {
|
|
||||||
it.consume { noMoreCall ->
|
|
||||||
if (noMoreCall) {
|
|
||||||
Log.i("[Call Activity] No more call event fired, finishing activity")
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
callsViewModel.askWriteExternalStoragePermissionEvent.observe(
|
|
||||||
this
|
|
||||||
) {
|
|
||||||
it.consume {
|
|
||||||
Log.i("[Call Activity] Asking for WRITE_EXTERNAL_STORAGE permission to take snapshot")
|
|
||||||
requestPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
controlsViewModel.askPermissionEvent.observe(
|
controlsViewModel.askPermissionEvent.observe(
|
||||||
this
|
this
|
||||||
) {
|
) {
|
||||||
|
@ -136,6 +116,26 @@ class CallActivity : ProximitySensorActivity() {
|
||||||
if (visible) statsViewModel.enable() else statsViewModel.disable()
|
if (visible) statsViewModel.enable() else statsViewModel.disable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
callsViewModel.noMoreCallEvent.observe(
|
||||||
|
this
|
||||||
|
) {
|
||||||
|
it.consume { noMoreCall ->
|
||||||
|
if (noMoreCall) {
|
||||||
|
Log.i("[Call Activity] No more call event fired, finishing activity")
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callsViewModel.askWriteExternalStoragePermissionEvent.observe(
|
||||||
|
this
|
||||||
|
) {
|
||||||
|
it.consume {
|
||||||
|
Log.i("[Call Activity] Asking for WRITE_EXTERNAL_STORAGE permission to take snapshot")
|
||||||
|
requestPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
callsViewModel.currentCallData.observe(
|
callsViewModel.currentCallData.observe(
|
||||||
this
|
this
|
||||||
) { callData ->
|
) { callData ->
|
||||||
|
@ -148,6 +148,15 @@ class CallActivity : ProximitySensorActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
callsViewModel.askPermissionEvent.observe(
|
||||||
|
this
|
||||||
|
) {
|
||||||
|
it.consume { permission ->
|
||||||
|
Log.i("[Call Activity] Asking for $permission permission")
|
||||||
|
requestPermissions(arrayOf(permission), 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
conferenceViewModel.conferenceExists.observe(
|
conferenceViewModel.conferenceExists.observe(
|
||||||
this
|
this
|
||||||
) { exists ->
|
) { exists ->
|
||||||
|
@ -281,7 +290,7 @@ class CallActivity : ProximitySensorActivity() {
|
||||||
when (permissions[i]) {
|
when (permissions[i]) {
|
||||||
Manifest.permission.RECORD_AUDIO -> if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
|
Manifest.permission.RECORD_AUDIO -> if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
|
||||||
Log.i("[Call Activity] RECORD_AUDIO permission has been granted")
|
Log.i("[Call Activity] RECORD_AUDIO permission has been granted")
|
||||||
controlsViewModel.updateMicState()
|
callsViewModel.updateMicState()
|
||||||
}
|
}
|
||||||
Manifest.permission.CAMERA -> if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
|
Manifest.permission.CAMERA -> if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
|
||||||
Log.i("[Call Activity] CAMERA permission has been granted")
|
Log.i("[Call Activity] CAMERA permission has been granted")
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
package org.linphone.activities.voip.viewmodels
|
package org.linphone.activities.voip.viewmodels
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import androidx.lifecycle.MediatorLiveData
|
import androidx.lifecycle.MediatorLiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
@ -43,6 +44,10 @@ class CallsViewModel : ViewModel() {
|
||||||
|
|
||||||
val chatAndCallsCount = MediatorLiveData<Int>()
|
val chatAndCallsCount = MediatorLiveData<Int>()
|
||||||
|
|
||||||
|
val isMicrophoneMuted = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
|
val isMuteMicrophoneEnabled = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
val askWriteExternalStoragePermissionEvent: MutableLiveData<Event<Boolean>> by lazy {
|
val askWriteExternalStoragePermissionEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||||
MutableLiveData<Event<Boolean>>()
|
MutableLiveData<Event<Boolean>>()
|
||||||
}
|
}
|
||||||
|
@ -63,6 +68,10 @@ class CallsViewModel : ViewModel() {
|
||||||
MutableLiveData<Event<Boolean>>()
|
MutableLiveData<Event<Boolean>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val askPermissionEvent: MutableLiveData<Event<String>> by lazy {
|
||||||
|
MutableLiveData<Event<String>>()
|
||||||
|
}
|
||||||
|
|
||||||
private val listener = object : CoreListenerStub() {
|
private val listener = object : CoreListenerStub() {
|
||||||
override fun onChatRoomRead(core: Core, chatRoom: ChatRoom) {
|
override fun onChatRoomRead(core: Core, chatRoom: ChatRoom) {
|
||||||
updateUnreadChatCount()
|
updateUnreadChatCount()
|
||||||
|
@ -145,6 +154,7 @@ class CallsViewModel : ViewModel() {
|
||||||
initCallList()
|
initCallList()
|
||||||
updateInactiveCallsCount()
|
updateInactiveCallsCount()
|
||||||
updateUnreadChatCount()
|
updateUnreadChatCount()
|
||||||
|
updateMicState()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCleared() {
|
override fun onCleared() {
|
||||||
|
@ -156,6 +166,17 @@ class CallsViewModel : ViewModel() {
|
||||||
super.onCleared()
|
super.onCleared()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun toggleMuteMicrophone() {
|
||||||
|
if (!PermissionHelper.get().hasRecordAudioPermission()) {
|
||||||
|
askPermissionEvent.value = Event(Manifest.permission.RECORD_AUDIO)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val micMuted = currentCallData.value?.call?.microphoneMuted ?: false
|
||||||
|
currentCallData.value?.call?.microphoneMuted = !micMuted
|
||||||
|
updateMicState()
|
||||||
|
}
|
||||||
|
|
||||||
fun mergeCallsIntoConference() {
|
fun mergeCallsIntoConference() {
|
||||||
Log.i("[Calls] Merging all calls into new conference")
|
Log.i("[Calls] Merging all calls into new conference")
|
||||||
val core = coreContext.core
|
val core = coreContext.core
|
||||||
|
@ -258,6 +279,7 @@ class CallsViewModel : ViewModel() {
|
||||||
currentCallData.value = viewModel
|
currentCallData.value = viewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateMicState()
|
||||||
// updateUnreadChatCount()
|
// updateUnreadChatCount()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,6 +292,11 @@ class CallsViewModel : ViewModel() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateMicState() {
|
||||||
|
isMicrophoneMuted.value = !PermissionHelper.get().hasRecordAudioPermission() || currentCallData.value?.call?.microphoneMuted == true
|
||||||
|
isMuteMicrophoneEnabled.value = currentCallData.value?.call != null
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateCallsAndChatCount(): Int {
|
private fun updateCallsAndChatCount(): Int {
|
||||||
return (inactiveCallsCount.value ?: 0) + (currentCallUnreadChatMessageCount.value ?: 0)
|
return (inactiveCallsCount.value ?: 0) + (currentCallUnreadChatMessageCount.value ?: 0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,10 +37,6 @@ import org.linphone.utils.Event
|
||||||
import org.linphone.utils.PermissionHelper
|
import org.linphone.utils.PermissionHelper
|
||||||
|
|
||||||
class ControlsViewModel : ViewModel() {
|
class ControlsViewModel : ViewModel() {
|
||||||
val isMicrophoneMuted = MutableLiveData<Boolean>()
|
|
||||||
|
|
||||||
val isMuteMicrophoneEnabled = MutableLiveData<Boolean>()
|
|
||||||
|
|
||||||
val isSpeakerSelected = MutableLiveData<Boolean>()
|
val isSpeakerSelected = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
val isBluetoothHeadsetSelected = MutableLiveData<Boolean>()
|
val isBluetoothHeadsetSelected = MutableLiveData<Boolean>()
|
||||||
|
@ -241,17 +237,6 @@ class ControlsViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleMuteMicrophone() {
|
|
||||||
if (!PermissionHelper.get().hasRecordAudioPermission()) {
|
|
||||||
askPermissionEvent.value = Event(Manifest.permission.RECORD_AUDIO)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val micEnabled = coreContext.core.isMicEnabled
|
|
||||||
coreContext.core.isMicEnabled = !micEnabled
|
|
||||||
updateMicState()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toggleSpeaker() {
|
fun toggleSpeaker() {
|
||||||
if (AudioRouteUtils.isSpeakerAudioRouteCurrentlyUsed()) {
|
if (AudioRouteUtils.isSpeakerAudioRouteCurrentlyUsed()) {
|
||||||
forceEarpieceAudioRoute()
|
forceEarpieceAudioRoute()
|
||||||
|
@ -402,16 +387,10 @@ class ControlsViewModel : ViewModel() {
|
||||||
private fun updateUI() {
|
private fun updateUI() {
|
||||||
updateVideoAvailable()
|
updateVideoAvailable()
|
||||||
updateVideoEnabled()
|
updateVideoEnabled()
|
||||||
updateMicState()
|
|
||||||
updateSpeakerState()
|
updateSpeakerState()
|
||||||
updateAudioRoutesState()
|
updateAudioRoutesState()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateMicState() {
|
|
||||||
isMicrophoneMuted.value = !PermissionHelper.get().hasRecordAudioPermission() || !coreContext.core.isMicEnabled
|
|
||||||
isMuteMicrophoneEnabled.value = coreContext.core.currentCall != null || coreContext.core.conference?.isIn == true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateSpeakerState() {
|
private fun updateSpeakerState() {
|
||||||
isSpeakerSelected.value = AudioRouteUtils.isSpeakerAudioRouteCurrentlyUsed()
|
isSpeakerSelected.value = AudioRouteUtils.isSpeakerAudioRouteCurrentlyUsed()
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,14 @@ class NativeCallWrapper(var callId: String) : Connection() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
call.microphoneMuted = state.isMuted
|
if (state.isMuted != call.microphoneMuted) {
|
||||||
|
Log.w("[Connection] Connection audio state asks for changing in mute: ${state.isMuted}, currently is ${call.microphoneMuted}")
|
||||||
|
if (state.isMuted) {
|
||||||
|
Log.w("[Connection] Muting microphone")
|
||||||
|
call.microphoneMuted = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
when (state.route) {
|
when (state.route) {
|
||||||
CallAudioState.ROUTE_EARPIECE -> AudioRouteUtils.routeAudioToEarpiece(call, true)
|
CallAudioState.ROUTE_EARPIECE -> AudioRouteUtils.routeAudioToEarpiece(call, true)
|
||||||
CallAudioState.ROUTE_SPEAKER -> AudioRouteUtils.routeAudioToSpeaker(call, true)
|
CallAudioState.ROUTE_SPEAKER -> AudioRouteUtils.routeAudioToSpeaker(call, true)
|
||||||
|
|
|
@ -44,11 +44,11 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginEnd="5dp"
|
android:layout_marginEnd="5dp"
|
||||||
android:background="@drawable/button_background_reverse"
|
android:background="@drawable/button_background_reverse"
|
||||||
android:contentDescription="@{controlsViewModel.isMicrophoneMuted ? @string/content_description_disable_mic_mute : @string/content_description_enable_mic_mute}"
|
android:contentDescription="@{callsViewModel.isMicrophoneMuted ? @string/content_description_disable_mic_mute : @string/content_description_enable_mic_mute}"
|
||||||
android:enabled="@{controlsViewModel.isMuteMicrophoneEnabled}"
|
android:enabled="@{callsViewModel.isMuteMicrophoneEnabled}"
|
||||||
android:onClick="@{() -> controlsViewModel.toggleMuteMicrophone()}"
|
android:onClick="@{() -> callsViewModel.toggleMuteMicrophone()}"
|
||||||
android:padding="5dp"
|
android:padding="5dp"
|
||||||
android:selected="@{controlsViewModel.isMicrophoneMuted}"
|
android:selected="@{callsViewModel.isMicrophoneMuted}"
|
||||||
android:src="@drawable/icon_toggle_mic"
|
android:src="@drawable/icon_toggle_mic"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintDimensionRatio="W,1:1"
|
app:layout_constraintDimensionRatio="W,1:1"
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
|
|
||||||
<import type="android.view.View" />
|
<import type="android.view.View" />
|
||||||
|
|
||||||
|
<variable
|
||||||
|
name="callsViewModel"
|
||||||
|
type="org.linphone.activities.voip.viewmodels.CallsViewModel" />
|
||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="controlsViewModel"
|
name="controlsViewModel"
|
||||||
type="org.linphone.activities.voip.viewmodels.ControlsViewModel" />
|
type="org.linphone.activities.voip.viewmodels.ControlsViewModel" />
|
||||||
|
@ -34,11 +38,11 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginEnd="5dp"
|
android:layout_marginEnd="5dp"
|
||||||
android:background="@drawable/button_background_reverse"
|
android:background="@drawable/button_background_reverse"
|
||||||
android:contentDescription="@{controlsViewModel.isMicrophoneMuted ? @string/content_description_disable_mic_mute : @string/content_description_enable_mic_mute}"
|
android:contentDescription="@{callsViewModel.isMicrophoneMuted ? @string/content_description_disable_mic_mute : @string/content_description_enable_mic_mute}"
|
||||||
android:enabled="@{controlsViewModel.isMuteMicrophoneEnabled}"
|
android:enabled="@{callsViewModel.isMuteMicrophoneEnabled}"
|
||||||
android:onClick="@{() -> controlsViewModel.toggleMuteMicrophone()}"
|
android:onClick="@{() -> callsViewModel.toggleMuteMicrophone()}"
|
||||||
android:padding="5dp"
|
android:padding="5dp"
|
||||||
android:selected="@{controlsViewModel.isMicrophoneMuted}"
|
android:selected="@{callsViewModel.isMicrophoneMuted}"
|
||||||
android:src="@drawable/icon_toggle_mic"
|
android:src="@drawable/icon_toggle_mic"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintDimensionRatio="W,1:1"
|
app:layout_constraintDimensionRatio="W,1:1"
|
||||||
|
|
|
@ -119,6 +119,7 @@
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="@dimen/voip_buttons_fragment_size"
|
android:layout_height="@dimen/voip_buttons_fragment_size"
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
|
app:callsViewModel="@{callsViewModel}"
|
||||||
app:controlsViewModel="@{controlsViewModel}"
|
app:controlsViewModel="@{controlsViewModel}"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
|
Loading…
Reference in a new issue