From fea42aba3b2c234ed843ab14998f3b555a1ba5bb Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 9 Apr 2024 11:09:22 +0200 Subject: [PATCH] Display our own video (if enabled) while waiting for other participants to join the conference --- .../fragment/ActiveConferenceCallFragment.kt | 48 +++++++++++++ .../viewmodel/ConferenceViewModel.kt | 67 ++++++++++++++----- .../call_active_conference_fragment.xml | 16 ++++- 3 files changed, 113 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/org/linphone/ui/call/conference/fragment/ActiveConferenceCallFragment.kt b/app/src/main/java/org/linphone/ui/call/conference/fragment/ActiveConferenceCallFragment.kt index 4e99cb21d..ea40f3160 100644 --- a/app/src/main/java/org/linphone/ui/call/conference/fragment/ActiveConferenceCallFragment.kt +++ b/app/src/main/java/org/linphone/ui/call/conference/fragment/ActiveConferenceCallFragment.kt @@ -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) + } } diff --git a/app/src/main/java/org/linphone/ui/call/conference/viewmodel/ConferenceViewModel.kt b/app/src/main/java/org/linphone/ui/call/conference/viewmodel/ConferenceViewModel.kt index 632ec7f83..4139826e2 100644 --- a/app/src/main/java/org/linphone/ui/call/conference/viewmodel/ConferenceViewModel.kt +++ b/app/src/main/java/org/linphone/ui/call/conference/viewmodel/ConferenceViewModel.kt @@ -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() + 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, diff --git a/app/src/main/res/layout/call_active_conference_fragment.xml b/app/src/main/res/layout/call_active_conference_fragment.xml index 2b4066ff8..0decc5c9f 100644 --- a/app/src/main/res/layout/call_active_conference_fragment.xml +++ b/app/src/main/res/layout/call_active_conference_fragment.xml @@ -235,6 +235,20 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"/> + +