diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/call/CallView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/call/CallView.kt
index 036228cb6..b6f529600 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/call/CallView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/call/CallView.kt
@@ -1,6 +1,8 @@
package chat.simplex.app.views.call
import android.Manifest
+import android.content.Context
+import android.media.AudioManager
import android.util.Log
import android.view.ViewGroup
import android.webkit.*
@@ -35,6 +37,7 @@ import chat.simplex.app.views.helpers.ProfileImage
import chat.simplex.app.views.helpers.withApi
import com.google.accompanist.permissions.rememberMultiplePermissionsState
import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
@@ -44,6 +47,8 @@ fun ActiveCallView(chatModel: ChatModel) {
val call = chatModel.activeCall.value
if (call != null) withApi { chatModel.callManager.endCall(call) }
})
+ val cxt = LocalContext.current
+ val scope = rememberCoroutineScope()
Box(Modifier.fillMaxSize()) {
WebRTCView(chatModel.callCommand) { apiMsg ->
Log.d(TAG, "received from WebRTCView: $apiMsg")
@@ -79,6 +84,10 @@ fun ActiveCallView(chatModel: ChatModel) {
}
is WCallResponse.Connected -> {
chatModel.activeCall.value = call.copy(callState = CallState.Connected, connectionInfo = r.connectionInfo)
+ scope.launch {
+ delay(2000L)
+ setCallSound(cxt, call)
+ }
}
is WCallResponse.Ended -> {
chatModel.activeCall.value = call.copy(callState = CallState.Ended)
@@ -117,21 +126,43 @@ fun ActiveCallView(chatModel: ChatModel) {
@Composable
private fun ActiveCallOverlay(call: Call, chatModel: ChatModel) {
+ var cxt = LocalContext.current
ActiveCallOverlayLayout(
call = call,
dismiss = { withApi { chatModel.callManager.endCall(call) } },
toggleAudio = { chatModel.callCommand.value = WCallCommand.Media(CallMediaType.Audio, enable = !call.audioEnabled) },
toggleVideo = { chatModel.callCommand.value = 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
+ setCallSound(cxt, call)
+ }
+ },
flipCamera = { chatModel.callCommand.value = WCallCommand.Camera(call.localCamera.flipped) }
)
}
+private fun setCallSound(cxt: Context, call: Call) {
+ Log.d(TAG, "setCallSound: set audio mode")
+ val am = cxt.getSystemService(Context.AUDIO_SERVICE) as AudioManager
+ if (call.soundSpeaker) {
+ am.mode = AudioManager.MODE_NORMAL
+ am.isSpeakerphoneOn = true
+ } else {
+ am.mode = AudioManager.MODE_IN_CALL
+ am.isSpeakerphoneOn = false
+ }
+}
+
@Composable
private fun ActiveCallOverlayLayout(
call: Call,
dismiss: () -> Unit,
toggleAudio: () -> Unit,
toggleVideo: () -> Unit,
+ toggleSound: () -> Unit,
flipCamera: () -> Unit
) {
Column(Modifier.padding(16.dp)) {
@@ -174,6 +205,11 @@ private fun ActiveCallOverlayLayout(
Box(Modifier.padding(start = 32.dp)) {
ToggleAudioButton(call, toggleAudio)
}
+ Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.CenterEnd) {
+ Box(Modifier.padding(end = 32.dp)) {
+ ToggleSoundButton(call, toggleSound)
+ }
+ }
}
}
}
@@ -194,12 +230,21 @@ private fun ControlButton(call: Call, icon: ImageVector, @StringRes iconText: In
@Composable
private fun ToggleAudioButton(call: Call, toggleAudio: () -> Unit) {
if (call.audioEnabled) {
- ControlButton(call, Icons.Outlined.Mic, R.string.icon_descr_video_off, toggleAudio)
+ ControlButton(call, Icons.Outlined.Mic, R.string.icon_descr_audio_off, toggleAudio)
} else {
ControlButton(call, Icons.Outlined.MicOff, R.string.icon_descr_audio_on, toggleAudio)
}
}
+@Composable
+private fun ToggleSoundButton(call: Call, toggleSound: () -> Unit) {
+ if (call.soundSpeaker) {
+ ControlButton(call, Icons.Outlined.VolumeUp, R.string.icon_descr_speaker_off, toggleSound)
+ } else {
+ ControlButton(call, Icons.Outlined.VolumeDown, R.string.icon_descr_speaker_on, toggleSound)
+ }
+}
+
@Composable
fun CallInfoView(call: Call, alignment: Alignment.Horizontal) {
@Composable fun InfoText(text: String, style: TextStyle = MaterialTheme.typography.body2) =
@@ -393,6 +438,7 @@ fun PreviewActiveCallOverlayVideo() {
dismiss = {},
toggleAudio = {},
toggleVideo = {},
+ toggleSound = {},
flipCamera = {}
)
}
@@ -413,6 +459,7 @@ fun PreviewActiveCallOverlayAudio() {
dismiss = {},
toggleAudio = {},
toggleVideo = {},
+ toggleSound = {},
flipCamera = {}
)
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/call/WebRTC.kt b/apps/android/app/src/main/java/chat/simplex/app/views/call/WebRTC.kt
index afef4ca82..bb079e800 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/call/WebRTC.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/call/WebRTC.kt
@@ -18,6 +18,7 @@ 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
) {
diff --git a/apps/android/app/src/main/res/values-ru/strings.xml b/apps/android/app/src/main/res/values-ru/strings.xml
index 16269f27a..c6a916f6c 100644
--- a/apps/android/app/src/main/res/values-ru/strings.xml
+++ b/apps/android/app/src/main/res/values-ru/strings.xml
@@ -404,6 +404,8 @@
Включить видео
Выключить звук
Включить звук
+ Выключить спикер
+ Включить спикер
Перевернуть камеру
diff --git a/apps/android/app/src/main/res/values/strings.xml b/apps/android/app/src/main/res/values/strings.xml
index 284fd2ca8..e327f0feb 100644
--- a/apps/android/app/src/main/res/values/strings.xml
+++ b/apps/android/app/src/main/res/values/strings.xml
@@ -406,6 +406,8 @@
Video on
Audio off
Audio on
+ Speaker off
+ Speaker on
Flip camera