mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 11:28:06 +00:00
Display our own video (if enabled) while waiting for other participants to join the conference
This commit is contained in:
parent
065cdfa8c1
commit
fea42aba3b
3 changed files with 113 additions and 18 deletions
|
|
@ -19,12 +19,14 @@
|
|||
*/
|
||||
package org.linphone.ui.call.conference.fragment
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.os.SystemClock
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
|
|
@ -83,6 +85,33 @@ class ActiveConferenceCallFragment : GenericCallFragment() {
|
|||
override fun onSlide(bottomSheet: View, slideOffset: Float) { }
|
||||
}
|
||||
|
||||
// For moving video preview purposes
|
||||
|
||||
private var previewX: Float = 0f
|
||||
private var previewY: Float = 0f
|
||||
|
||||
private val previewTouchListener = View.OnTouchListener { view, event ->
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
previewX = view.x - event.rawX
|
||||
previewY = view.y - event.rawY
|
||||
true
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
view.animate()
|
||||
.x(event.rawX + previewX)
|
||||
.y(event.rawY + previewY)
|
||||
.setDuration(0)
|
||||
.start()
|
||||
true
|
||||
}
|
||||
else -> {
|
||||
view.performClick()
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
|
|
@ -163,6 +192,15 @@ class ActiveConferenceCallFragment : GenericCallFragment() {
|
|||
actionsBottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
|
||||
}
|
||||
|
||||
callViewModel.conferenceModel.participants.observe(viewLifecycleOwner) { participants ->
|
||||
coreContext.postOnCoreThread { core ->
|
||||
if (participants.size == 1) {
|
||||
Log.i("$TAG We are alone in that conference, using nativePreviewWindowId")
|
||||
core.nativePreviewWindowId = binding.localPreviewVideoSurface
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.setBackClickListener {
|
||||
requireActivity().finish()
|
||||
}
|
||||
|
|
@ -201,12 +239,22 @@ class ActiveConferenceCallFragment : GenericCallFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
coreContext.postOnCoreThread {
|
||||
binding.localPreviewVideoSurface.setOnTouchListener(previewTouchListener)
|
||||
|
||||
// Need to be done manually
|
||||
callViewModel.updateCallDuration()
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
|
||||
binding.localPreviewVideoSurface.setOnTouchListener(null)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,9 +102,9 @@ class ConferenceViewModel {
|
|||
) {
|
||||
if (conference.isMe(device.address)) {
|
||||
val direction = device.getStreamCapability(StreamType.Video)
|
||||
isMeParticipantSendingVideo.postValue(
|
||||
direction == MediaDirection.SendRecv || direction == MediaDirection.SendOnly
|
||||
)
|
||||
val sendingVideo = direction == MediaDirection.SendRecv || direction == MediaDirection.SendOnly
|
||||
isMeParticipantSendingVideo.postValue(sendingVideo)
|
||||
Log.i("$TAG We ${if (sendingVideo) "are" else "aren't"} sending video")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -147,7 +147,24 @@ class ConferenceViewModel {
|
|||
Log.i(
|
||||
"$TAG Participant device added: ${participantDevice.address.asStringUriOnly()}"
|
||||
)
|
||||
addParticipantDevice(participantDevice)
|
||||
|
||||
// Since we do not compute our own devices until another participant joins,
|
||||
// We have to do it when someone else joins
|
||||
if (participantDevices.value.orEmpty().isEmpty()) {
|
||||
val list = arrayListOf<ConferenceParticipantDeviceModel>()
|
||||
val ourDevices = conference.me.devices
|
||||
Log.i("$TAG We have [${ourDevices.size}] devices, now it's time to add them")
|
||||
for (device in ourDevices) {
|
||||
val model = ConferenceParticipantDeviceModel(device, true)
|
||||
list.add(model)
|
||||
}
|
||||
|
||||
val newModel = ConferenceParticipantDeviceModel(participantDevice)
|
||||
list.add(newModel)
|
||||
participantDevices.postValue(sortParticipantDevicesList(list))
|
||||
} else {
|
||||
addParticipantDevice(participantDevice)
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
|
|
@ -202,6 +219,10 @@ class ConferenceViewModel {
|
|||
override fun onStateChanged(conference: Conference, state: Conference.State) {
|
||||
Log.i("$TAG State changed [$state]")
|
||||
if (conference.state == Conference.State.Created) {
|
||||
val isIn = conference.isIn
|
||||
isPaused.postValue(!isIn)
|
||||
Log.i("$TAG We ${if (isIn) "are" else "aren't"} in the conference")
|
||||
|
||||
computeParticipants()
|
||||
}
|
||||
}
|
||||
|
|
@ -226,15 +247,20 @@ class ConferenceViewModel {
|
|||
isCurrentCallInConference.postValue(true)
|
||||
conference = conf
|
||||
conference.addListener(conferenceListener)
|
||||
isPaused.postValue(conference.isIn)
|
||||
|
||||
val isIn = conference.isIn
|
||||
isPaused.postValue(!isIn)
|
||||
Log.i("$TAG We ${if (isIn) "are" else "aren't"} in the conference right now")
|
||||
|
||||
val screenSharing = conference.screenSharingParticipant != null
|
||||
isScreenSharing.postValue(screenSharing)
|
||||
|
||||
val confSubject = conference.subject.orEmpty()
|
||||
Log.i(
|
||||
"$TAG Configuring conference with subject [${conference.subject}] from call [${call.callLog.callId}]"
|
||||
"$TAG Configuring conference with subject [$confSubject] from call [${call.callLog.callId}]"
|
||||
)
|
||||
sipUri.postValue(conference.conferenceAddress.asStringUriOnly())
|
||||
subject.postValue(conference.subject)
|
||||
subject.postValue(confSubject)
|
||||
|
||||
if (conference.state == Conference.State.Created) {
|
||||
computeParticipants()
|
||||
|
|
@ -420,10 +446,10 @@ class ConferenceViewModel {
|
|||
val meParticipantModel = ConferenceParticipantModel(meParticipant, admin, true, null, null)
|
||||
participantsList.add(meParticipantModel)
|
||||
|
||||
if (!skipDevices) {
|
||||
val ourDevices = conference.me.devices
|
||||
Log.i("$TAG We have [${ourDevices.size}] devices")
|
||||
for (device in ourDevices) {
|
||||
val ourDevices = conference.me.devices
|
||||
Log.i("$TAG We have [${ourDevices.size}] devices")
|
||||
for (device in ourDevices) {
|
||||
if (!skipDevices) {
|
||||
val model = ConferenceParticipantDeviceModel(device, true)
|
||||
devicesList.add(model)
|
||||
|
||||
|
|
@ -433,12 +459,12 @@ class ConferenceViewModel {
|
|||
activeSpeaker.postValue(model)
|
||||
activeSpeakerParticipantDeviceFound = true
|
||||
}
|
||||
|
||||
val direction = device.getStreamCapability(StreamType.Video)
|
||||
isMeParticipantSendingVideo.postValue(
|
||||
direction == MediaDirection.SendRecv || direction == MediaDirection.SendOnly
|
||||
)
|
||||
}
|
||||
|
||||
val direction = device.getStreamCapability(StreamType.Video)
|
||||
val sendingVideo = direction == MediaDirection.SendRecv || direction == MediaDirection.SendOnly
|
||||
isMeParticipantSendingVideo.postValue(sendingVideo)
|
||||
Log.i("$TAG We ${if (sendingVideo) "are" else "aren't"} sending video right now")
|
||||
}
|
||||
|
||||
if (!activeSpeakerParticipantDeviceFound && devicesList.isNotEmpty()) {
|
||||
|
|
@ -453,7 +479,14 @@ class ConferenceViewModel {
|
|||
participants.postValue(sortParticipantList(participantsList))
|
||||
if (!skipDevices) {
|
||||
checkIfTooManyParticipantDevicesForGridLayout(devicesList)
|
||||
participantDevices.postValue(sortParticipantDevicesList(devicesList))
|
||||
|
||||
if (participantsList.size == 1) {
|
||||
Log.i("$TAG We are alone in that conference, not posting devices list for now")
|
||||
participantDevices.postValue(arrayListOf())
|
||||
} else {
|
||||
participantDevices.postValue(sortParticipantDevicesList(devicesList))
|
||||
}
|
||||
|
||||
participantsLabel.postValue(
|
||||
AppUtils.getStringWithPlural(
|
||||
R.plurals.conference_participants_list_title,
|
||||
|
|
|
|||
|
|
@ -235,6 +235,20 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<org.linphone.ui.call.view.RoundCornersTextureView
|
||||
android:id="@+id/local_preview_video_surface"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginBottom="@{viewModel.fullScreenMode || viewModel.pipMode ? @dimen/zero : @dimen/call_main_actions_menu_margin, default=@dimen/call_main_actions_menu_margin}"
|
||||
android:visibility="@{conferenceViewModel.isMeParticipantSendingVideo && conferenceViewModel.participants.size() == 1 && !conferenceViewModel.isPaused ? View.VISIBLE : View.GONE}"
|
||||
app:alignTopRight="true"
|
||||
app:displayMode="black_bars"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHeight_max="200dp"
|
||||
app:layout_constraintWidth_max="200dp" />
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/conference_layout_nav_host_fragment"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
|
|
@ -242,7 +256,7 @@
|
|||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="@{viewModel.fullScreenMode || viewModel.pipMode ? @dimen/zero : @dimen/call_main_actions_menu_margin, default=@dimen/call_main_actions_menu_margin}"
|
||||
android:layout_marginTop="@{viewModel.fullScreenMode || viewModel.pipMode ? @dimen/zero : @dimen/call_remote_video_top_margin, default=@dimen/call_remote_video_top_margin}"
|
||||
android:visibility="@{conferenceViewModel.participantDevices.size() > 1 && !conferenceViewModel.isPaused ? View.VISIBLE : View.GONE}"
|
||||
android:visibility="@{conferenceViewModel.participants.size() > 1 && !conferenceViewModel.isPaused ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:navGraph="@navigation/conference_nav_graph"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue