diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/call/CallAudioDeviceManager.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/call/CallAudioDeviceManager.kt index d1376196a9..d9562100cf 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/call/CallAudioDeviceManager.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/call/CallAudioDeviceManager.kt @@ -18,7 +18,7 @@ interface CallAudioDeviceManagerInterface { fun start() fun stop() // AudioDeviceInfo.AudioDeviceType - fun selectLastExternalDeviceOrDefault(speaker: Boolean, keepAnyNonEarpiece: Boolean) + fun selectLastExternalDeviceOrDefault(speaker: Boolean, keepAnyExternal: Boolean) // AudioDeviceInfo.AudioDeviceType fun selectDevice(id: Int) @@ -74,24 +74,24 @@ class PostSCallAudioDeviceManager: CallAudioDeviceManagerInterface { am.removeOnCommunicationDeviceChangedListener(listener) } - override fun selectLastExternalDeviceOrDefault(speaker: Boolean, keepAnyNonEarpiece: Boolean) { + override fun selectLastExternalDeviceOrDefault(speaker: Boolean, keepAnyExternal: Boolean) { Log.d(TAG, "selectLastExternalDeviceOrDefault: set audio mode, speaker enabled: $speaker") val commDevice = am.communicationDevice - if (keepAnyNonEarpiece && commDevice != null && commDevice.type != AudioDeviceInfo.TYPE_BUILTIN_EARPIECE) { - // some external device or speaker selected already, no need to change it + if (keepAnyExternal && commDevice != null && commDevice.type != AudioDeviceInfo.TYPE_BUILTIN_EARPIECE && commDevice.type != AudioDeviceInfo.TYPE_BUILTIN_SPEAKER) { + // some external device selected already, no need to change it return } - val preferredSecondaryDevice = if (speaker) AudioDeviceInfo.TYPE_BUILTIN_SPEAKER else AudioDeviceInfo.TYPE_BUILTIN_EARPIECE - val externalDevice = devices.value.lastOrNull { it.type != AudioDeviceInfo.TYPE_BUILTIN_SPEAKER && it.type != AudioDeviceInfo.TYPE_BUILTIN_EARPIECE } + val preferredInternalDevice = if (speaker) AudioDeviceInfo.TYPE_BUILTIN_SPEAKER else AudioDeviceInfo.TYPE_BUILTIN_EARPIECE + val externalDevice = devices.value.lastOrNull { it.type != AudioDeviceInfo.TYPE_BUILTIN_EARPIECE && it.type != AudioDeviceInfo.TYPE_BUILTIN_SPEAKER } // External device already selected if (externalDevice != null && externalDevice.type == am.communicationDevice?.type) { return } if (externalDevice != null) { am.setCommunicationDevice(externalDevice) - } else if (am.communicationDevice?.type != preferredSecondaryDevice) { - am.availableCommunicationDevices.firstOrNull { it.type == preferredSecondaryDevice }?.let { + } else if (am.communicationDevice?.type != preferredInternalDevice) { + am.availableCommunicationDevices.firstOrNull { it.type == preferredInternalDevice }?.let { am.setCommunicationDevice(it) } } @@ -136,25 +136,25 @@ class PreSCallAudioDeviceManager: CallAudioDeviceManagerInterface { am.stopBluetoothSco() } - override fun selectLastExternalDeviceOrDefault(speaker: Boolean, keepAnyNonEarpiece: Boolean) { + override fun selectLastExternalDeviceOrDefault(speaker: Boolean, keepAnyExternal: Boolean) { Log.d(TAG, "selectLastExternalDeviceOrDefault: set audio mode, speaker enabled: $speaker") - val preferredSecondaryDevice = if (speaker) AudioDeviceInfo.TYPE_BUILTIN_SPEAKER else AudioDeviceInfo.TYPE_BUILTIN_EARPIECE - val externalDevice = devices.value.lastOrNull { it.type != AudioDeviceInfo.TYPE_BUILTIN_SPEAKER && it.type != AudioDeviceInfo.TYPE_BUILTIN_EARPIECE } + val preferredInternalDevice = if (speaker) AudioDeviceInfo.TYPE_BUILTIN_SPEAKER else AudioDeviceInfo.TYPE_BUILTIN_EARPIECE + val externalDevice = devices.value.lastOrNull { it.type != AudioDeviceInfo.TYPE_BUILTIN_EARPIECE && it.type != AudioDeviceInfo.TYPE_BUILTIN_SPEAKER } if (externalDevice != null) { selectDevice(externalDevice.id) } else { am.stopBluetoothSco() am.isWiredHeadsetOn = false - am.isSpeakerphoneOn = preferredSecondaryDevice == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER + am.isSpeakerphoneOn = preferredInternalDevice == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER am.isBluetoothScoOn = false - val newCurrentDevice = devices.value.firstOrNull { it.type == preferredSecondaryDevice } + val newCurrentDevice = devices.value.firstOrNull { it.type == preferredInternalDevice } adaptToCurrentlyActiveDevice(newCurrentDevice) } } override fun selectDevice(id: Int) { val device = devices.value.lastOrNull { it.id == id } - val isExternalDevice = device != null && device.type != AudioDeviceInfo.TYPE_BUILTIN_SPEAKER && device.type != AudioDeviceInfo.TYPE_BUILTIN_EARPIECE + val isExternalDevice = device != null && device.type != AudioDeviceInfo.TYPE_BUILTIN_EARPIECE && device.type != AudioDeviceInfo.TYPE_BUILTIN_SPEAKER if (isExternalDevice) { am.isSpeakerphoneOn = false if (device?.type == AudioDeviceInfo.TYPE_WIRED_HEADSET || device?.type == AudioDeviceInfo.TYPE_WIRED_HEADPHONES) { diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/call/CallView.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/call/CallView.android.kt index 382d87dccb..f9fb81a3ef 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/call/CallView.android.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/call/CallView.android.kt @@ -26,7 +26,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow @@ -126,7 +125,7 @@ actual fun ActiveCallView() { // Starting is delayed to make Android <= 11 working good with Bluetooth callAudioDeviceManager.start() } else { - callAudioDeviceManager.selectLastExternalDeviceOrDefault(call.soundSpeaker, true) + callAudioDeviceManager.selectLastExternalDeviceOrDefault(call.supportsVideo(), true) } CallSoundsPlayer.startConnectingCallSound(scope) activeCallWaitDeliveryReceipt(scope) @@ -138,7 +137,7 @@ actual fun ActiveCallView() { // Starting is delayed to make Android <= 11 working good with Bluetooth callAudioDeviceManager.start() } else { - callAudioDeviceManager.selectLastExternalDeviceOrDefault(call.soundSpeaker, true) + callAudioDeviceManager.selectLastExternalDeviceOrDefault(call.supportsVideo(), true) } } is WCallResponse.Answer -> withBGApi { @@ -241,11 +240,10 @@ private fun ActiveCallOverlay(call: Call, chatModel: ChatModel, callAudioDeviceM selectDevice = { callAudioDeviceManager.selectDevice(it.id) }, toggleVideo = { chatModel.callCommand.add(WCallCommand.Media(CallMediaType.Video, enable = !call.videoEnabled)) }, toggleSound = { - var call = chatModel.activeCall.value - if (call != null) { - call = call.copy(soundSpeaker = !call.soundSpeaker) - chatModel.activeCall.value = call - callAudioDeviceManager.selectLastExternalDeviceOrDefault(call.soundSpeaker, true) + val enableSpeaker = callAudioDeviceManager.currentDevice.value?.type == AudioDeviceInfo.TYPE_BUILTIN_EARPIECE + val preferredInternalDevice = callAudioDeviceManager.devices.value.firstOrNull { it.type == if (enableSpeaker) AudioDeviceInfo.TYPE_BUILTIN_SPEAKER else AudioDeviceInfo.TYPE_BUILTIN_EARPIECE } + if (preferredInternalDevice != null) { + callAudioDeviceManager.selectDevice(preferredInternalDevice.id) } }, flipCamera = { chatModel.callCommand.add(WCallCommand.Camera(call.localCamera.flipped)) } @@ -308,7 +306,8 @@ private fun ActiveCallOverlayLayout( currentDevice.value == null || devices.none { it.id == currentDevice.value?.id } ) { - ToggleSoundButton(call, enabled, toggleSound) + val isSpeaker = currentDevice.value?.type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER + ToggleSoundButton(call, enabled, isSpeaker, toggleSound) } else { ExposedDropDownSettingWithIcon( devices.map { Triple(it, it.icon, if (it.name != null) generalGetString(it.name!!) else it.productName.toString()) }, @@ -404,8 +403,8 @@ private fun ToggleAudioButton(call: Call, enabled: Boolean = true, toggleAudio: } @Composable -private fun ToggleSoundButton(call: Call, enabled: Boolean, toggleSound: () -> Unit) { - if (call.soundSpeaker) { +private fun ToggleSoundButton(call: Call, enabled: Boolean, speaker: Boolean, toggleSound: () -> Unit) { + if (speaker) { ControlButton(call, painterResource(MR.images.ic_volume_up), MR.strings.icon_descr_speaker_off, enabled, toggleSound) } else { ControlButton(call, painterResource(MR.images.ic_volume_down), MR.strings.icon_descr_speaker_on, enabled, toggleSound) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/call/WebRTC.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/call/WebRTC.kt index 4991cf13bc..0a7231370b 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/call/WebRTC.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/call/WebRTC.kt @@ -20,7 +20,6 @@ data class Call( val sharedKey: String? = null, val audioEnabled: Boolean = true, val videoEnabled: Boolean = localMedia == CallMediaType.Video, - val soundSpeaker: Boolean = localMedia == CallMediaType.Video, var localCamera: VideoCamera = VideoCamera.User, val connectionInfo: ConnectionInfo? = null, var connectedAt: Instant? = null,