mirror of
https://github.com/element-hq/element-android
synced 2024-11-28 13:38:49 +03:00
Toggle HD/SD
This commit is contained in:
parent
f3e2a55869
commit
374790176f
9 changed files with 97 additions and 16 deletions
|
@ -19,11 +19,14 @@ package im.vector.riotx.features.call
|
|||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.platform.VectorBaseBottomSheetDialogFragment
|
||||
import kotlinx.android.synthetic.main.activity_call.*
|
||||
import kotlinx.android.synthetic.main.bottom_sheet_call_controls.*
|
||||
import kotlinx.android.synthetic.main.vector_preference_push_rule.view.*
|
||||
import me.gujun.android.span.span
|
||||
|
||||
class CallControlsBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
||||
|
@ -47,6 +50,11 @@ class CallControlsBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
|||
dismiss()
|
||||
}
|
||||
|
||||
callControlsToggleSDHD.clickableView.debouncedClicks {
|
||||
callViewModel.handle(VectorCallViewActions.ToggleHDSD)
|
||||
dismiss()
|
||||
}
|
||||
|
||||
callViewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is VectorCallViewEvents.ShowSoundDeviceChooser -> {
|
||||
|
@ -112,5 +120,20 @@ class CallControlsBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
|||
|
||||
callControlsSwitchCamera.isVisible = state.canSwitchCamera
|
||||
callControlsSwitchCamera.subTitle = getString(if (state.isFrontCamera) R.string.call_camera_front else R.string.call_camera_back)
|
||||
|
||||
if (state.isVideoCall) {
|
||||
callControlsToggleSDHD.isVisible = true
|
||||
if (state.isHD) {
|
||||
callControlsToggleSDHD.title = getString(R.string.call_format_turn_hd_off)
|
||||
callControlsToggleSDHD.subTitle = null
|
||||
callControlsToggleSDHD.leftIcon = ContextCompat.getDrawable(requireContext(), R.drawable.ic_hd)
|
||||
} else {
|
||||
callControlsToggleSDHD.title = getString(R.string.call_format_turn_hd_on)
|
||||
callControlsToggleSDHD.subTitle = null
|
||||
callControlsToggleSDHD.leftIcon = ContextCompat.getDrawable(requireContext(), R.drawable.ic_hd_disabled)
|
||||
}
|
||||
} else {
|
||||
callControlsToggleSDHD.isVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,3 +25,8 @@ data class CameraProxy(
|
|||
val name: String,
|
||||
val type: CameraType
|
||||
)
|
||||
|
||||
sealed class CaptureFormat(val width: Int, val height: Int, val fps: Int) {
|
||||
object HD : CaptureFormat(1280, 720, 30)
|
||||
object SD : CaptureFormat(640, 480, 30)
|
||||
}
|
||||
|
|
|
@ -33,12 +33,12 @@ class SharedActiveCallViewModel @Inject constructor(
|
|||
|
||||
val activeCall: MutableLiveData<MxCall?> = MutableLiveData()
|
||||
|
||||
val callStateListener = object: MxCall.StateListener {
|
||||
val callStateListener = object : MxCall.StateListener {
|
||||
|
||||
override fun onStateUpdate(call: MxCall) {
|
||||
if (activeCall.value?.callId == call.callId) {
|
||||
activeCall.postValue(call)
|
||||
}
|
||||
if (activeCall.value?.callId == call.callId) {
|
||||
activeCall.postValue(call)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,10 +48,6 @@ class SharedActiveCallViewModel @Inject constructor(
|
|||
activeCall.postValue(call)
|
||||
call?.addListener(callStateListener)
|
||||
}
|
||||
|
||||
override fun onCaptureStateChanged(captureInError: Boolean) {
|
||||
// nop
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
|
|
|
@ -48,6 +48,7 @@ data class VectorCallViewState(
|
|||
val isAudioMuted: Boolean = false,
|
||||
val isVideoEnabled: Boolean = true,
|
||||
val isVideoCaptureInError: Boolean = false,
|
||||
val isHD: Boolean = false,
|
||||
val isFrontCamera: Boolean = true,
|
||||
val canSwitchCamera: Boolean = true,
|
||||
val soundDevice: CallAudioManager.SoundDevice = CallAudioManager.SoundDevice.PHONE,
|
||||
|
@ -66,6 +67,7 @@ sealed class VectorCallViewActions : VectorViewModelAction {
|
|||
object SwitchSoundDevice : VectorCallViewActions()
|
||||
object HeadSetButtonPressed : VectorCallViewActions()
|
||||
object ToggleCamera : VectorCallViewActions()
|
||||
object ToggleHDSD : VectorCallViewActions()
|
||||
}
|
||||
|
||||
sealed class VectorCallViewEvents : VectorViewEvents {
|
||||
|
@ -129,9 +131,12 @@ class VectorCallViewModel @AssistedInject constructor(
|
|||
override fun onCurrentCallChange(call: MxCall?) {
|
||||
}
|
||||
|
||||
override fun onCaptureStateChanged(captureInError: Boolean) {
|
||||
override fun onCaptureStateChanged(mgr: WebRtcPeerConnectionManager) {
|
||||
setState {
|
||||
copy(isVideoCaptureInError = captureInError)
|
||||
copy(
|
||||
isVideoCaptureInError = mgr.capturerIsInError,
|
||||
isHD = mgr.currentCaptureFormat() is CaptureFormat.HD
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,7 +179,8 @@ class VectorCallViewModel @AssistedInject constructor(
|
|||
soundDevice = webRtcPeerConnectionManager.audioManager.getCurrentSoundDevice(),
|
||||
availableSoundDevices = webRtcPeerConnectionManager.audioManager.getAvailableSoundDevices(),
|
||||
isFrontCamera = webRtcPeerConnectionManager.currentCameraType() == CameraType.FRONT,
|
||||
canSwitchCamera = webRtcPeerConnectionManager.canSwitchCamera()
|
||||
canSwitchCamera = webRtcPeerConnectionManager.canSwitchCamera(),
|
||||
isHD = mxCall.isVideoCall && webRtcPeerConnectionManager.currentCaptureFormat() is CaptureFormat.HD
|
||||
)
|
||||
}
|
||||
} ?: run {
|
||||
|
@ -253,6 +259,10 @@ class VectorCallViewModel @AssistedInject constructor(
|
|||
VectorCallViewActions.ToggleCamera -> {
|
||||
webRtcPeerConnectionManager.switchCamera()
|
||||
}
|
||||
VectorCallViewActions.ToggleHDSD -> {
|
||||
if (!state.isVideoCall) return@withState
|
||||
webRtcPeerConnectionManager.setCaptureFormat(if (state.isHD) CaptureFormat.SD else CaptureFormat.HD)
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||
|
||||
interface CurrentCallListener {
|
||||
fun onCurrentCallChange(call: MxCall?)
|
||||
fun onCaptureStateChanged(captureInError: Boolean)
|
||||
fun onCaptureStateChanged(mgr: WebRtcPeerConnectionManager) {}
|
||||
fun onAudioDevicesChange(mgr: WebRtcPeerConnectionManager) {}
|
||||
fun onCameraChange(mgr: WebRtcPeerConnectionManager) {}
|
||||
}
|
||||
|
@ -165,11 +165,13 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||
private val availableCamera = ArrayList<CameraProxy>()
|
||||
private var cameraInUse: CameraProxy? = null
|
||||
|
||||
private var currentCaptureMode: CaptureFormat = CaptureFormat.HD
|
||||
|
||||
var capturerIsInError = false
|
||||
set(value) {
|
||||
field = value
|
||||
currentCallsListeners.forEach {
|
||||
tryThis { it.onCaptureStateChanged(value) }
|
||||
tryThis { it.onCaptureStateChanged(this) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -336,7 +338,7 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||
// Fallback for old android, try to restart capture when attached
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP && capturerIsInError && call.mxCall.isVideoCall) {
|
||||
// try to restart capture?
|
||||
videoCapturer?.startCapture(1280, 720, 30)
|
||||
videoCapturer?.startCapture(currentCaptureMode.width, currentCaptureMode.height, currentCaptureMode.fps)
|
||||
}
|
||||
// sink existing tracks (configuration change, e.g screen rotation)
|
||||
attachViewRenderersInternal()
|
||||
|
@ -463,7 +465,7 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||
|
||||
videoCapturer.initialize(surfaceTextureHelper, context.applicationContext, videoSource!!.capturerObserver)
|
||||
// HD
|
||||
videoCapturer.startCapture(1280, 720, 30)
|
||||
videoCapturer.startCapture(currentCaptureMode.width, currentCaptureMode.height, currentCaptureMode.fps)
|
||||
this.videoCapturer = videoCapturer
|
||||
|
||||
val localVideoTrack = peerConnectionFactory!!.createVideoTrack("ARDAMSv0", videoSource)
|
||||
|
@ -706,6 +708,21 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||
return cameraInUse?.type
|
||||
}
|
||||
|
||||
fun setCaptureFormat(format: CaptureFormat) {
|
||||
Timber.v("## VOIP setCaptureFormat $format")
|
||||
currentCall ?: return
|
||||
executor.execute {
|
||||
// videoCapturer?.stopCapture()
|
||||
videoCapturer?.changeCaptureFormat(format.width, format.height, format.fps)
|
||||
currentCaptureMode = format
|
||||
currentCallsListeners.forEach { tryThis { it.onCaptureStateChanged(this) } }
|
||||
}
|
||||
}
|
||||
|
||||
fun currentCaptureFormat(): CaptureFormat {
|
||||
return currentCaptureMode
|
||||
}
|
||||
|
||||
fun endCall() {
|
||||
// Update service state
|
||||
CallService.onNoActiveCall(context)
|
||||
|
@ -971,7 +988,7 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||
if (this.cameraId == cameraId && currentCall?.mxCall?.callId == callId) {
|
||||
// re-start the capture
|
||||
// TODO notify that video is enabled
|
||||
videoCapturer?.startCapture(1280, 720, 30)
|
||||
videoCapturer?.startCapture(currentCaptureMode.width, currentCaptureMode.height, currentCaptureMode.fps)
|
||||
(context.getSystemService(Context.CAMERA_SERVICE) as? CameraManager)
|
||||
?.unregisterAvailabilityCallback(this)
|
||||
}
|
||||
|
|
9
vector/src/main/res/drawable/ic_hd.xml
Normal file
9
vector/src/main/res/drawable/ic_hd.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M19,3H5C3.89,3 3,3.9 3,5V19C3,20.1 3.89,21 5,21H19C20.1,21 21,20.1 21,19V5C21,3.9 20.1,3 19,3ZM11,15H9.5V13H7.5V15H6V9H7.5V11.5H9.5V9H11V15ZM13,9H17C17.55,9 18,9.45 18,10V14C18,14.55 17.55,15 17,15H13V9ZM14.5,13.5H16.5V10.5H14.5V13.5Z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
9
vector/src/main/res/drawable/ic_hd_disabled.xml
Normal file
9
vector/src/main/res/drawable/ic_hd_disabled.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M17.5,15V13H18.6L19.5,15H21L20.1,12.9C20.6,12.7 21,12.1 21,11.5V10.5C21,9.7 20.3,9 19.5,9H16V13.9L17.1,15H17.5ZM17.5,10.5H19.5V11.5H17.5V10.5ZM13,10.5V10.9L14.5,12.4V10.5C14.5,9.7 13.8,9 13,9H11.1L12.6,10.5H13ZM9.5,9.5L2.5,2.5L1.4,3.5L6.9,9H6.5V11H4.5V9H3V15H4.5V12.5H6.5V15H8V10.1L9.5,11.6V15H12.9L20.5,22.6L21.6,21.5L9.5,9.5Z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
|
@ -25,4 +25,13 @@
|
|||
app:leftIcon="@drawable/ic_video_flip"
|
||||
app:tint="?attr/riotx_text_primary" />
|
||||
|
||||
<im.vector.riotx.core.ui.views.BottomSheetActionButton
|
||||
android:id="@+id/callControlsToggleSDHD"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:actionTitle="@string/call_switch_camera"
|
||||
tools:actionDescription="Front"
|
||||
app:leftIcon="@drawable/ic_hd"
|
||||
app:tint="?attr/riotx_text_primary" />
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
@ -222,6 +222,9 @@
|
|||
<string name="call_switch_camera">Switch Camera</string>
|
||||
<string name="call_camera_front">Front</string>
|
||||
<string name="call_camera_back">Back</string>
|
||||
<string name="call_format_turn_hd_off">Turn HD off</string>
|
||||
<string name="call_format_turn_hd_on">Turn HD on</string>
|
||||
|
||||
|
||||
|
||||
<string name="option_send_files">Send files</string>
|
||||
|
|
Loading…
Reference in a new issue