Added joining state to conference participant device

This commit is contained in:
Sylvain Berfini 2022-07-07 14:58:06 +02:00
parent 1fbac6e4d5
commit f1628060c6
10 changed files with 116 additions and 77 deletions

View file

@ -25,10 +25,7 @@ import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.contact.GenericContactData
import org.linphone.core.MediaDirection
import org.linphone.core.ParticipantDevice
import org.linphone.core.ParticipantDeviceListenerStub
import org.linphone.core.StreamType
import org.linphone.core.*
import org.linphone.core.tools.Log
class ConferenceParticipantDeviceData(
@ -42,12 +39,14 @@ class ConferenceParticipantDeviceData(
val isSendingVideo = MutableLiveData<Boolean>()
val activeSpeaker = MutableLiveData<Boolean>()
val isSpeaking = MutableLiveData<Boolean>()
val micMuted = MutableLiveData<Boolean>()
val isMuted = MutableLiveData<Boolean>()
val isInConference = MutableLiveData<Boolean>()
val isJoining = MutableLiveData<Boolean>()
private var textureView: TextureView? = null
private val listener = object : ParticipantDeviceListenerStub() {
@ -56,23 +55,31 @@ class ConferenceParticipantDeviceData(
isSpeaking: Boolean
) {
Log.i("[Conference Participant Device] Participant [${participantDevice.address.asStringUriOnly()}] is ${if (isSpeaking) "speaking" else "not speaking"}")
activeSpeaker.value = isSpeaking
this@ConferenceParticipantDeviceData.isSpeaking.value = isSpeaking
}
override fun onIsMuted(participantDevice: ParticipantDevice, isMuted: Boolean) {
Log.i("[Conference Participant Device] Participant [${participantDevice.address.asStringUriOnly()}] is ${if (isMuted) "muted" else "not muted"}")
micMuted.value = isMuted
this@ConferenceParticipantDeviceData.isMuted.value = isMuted
}
override fun onConferenceJoined(participantDevice: ParticipantDevice) {
Log.i("[Conference Participant Device] Participant [${participantDevice.address.asStringUriOnly()}] has joined the conference")
isInConference.value = true
updateWindowId(textureView)
}
override fun onConferenceLeft(participantDevice: ParticipantDevice) {
Log.i("[Conference Participant Device] Participant [${participantDevice.address.asStringUriOnly()}] has left the conference")
isInConference.value = false
override fun onStateChanged(
participantDevice: ParticipantDevice,
state: ParticipantDeviceState
) {
Log.i("[Conference Participant Device] Participant [${participantDevice.address.asStringUriOnly()}] state has changed: $state")
when (state) {
ParticipantDeviceState.Joining, ParticipantDeviceState.Alerting -> isJoining.value = true
ParticipantDeviceState.OnHold -> {
isInConference.value = false
}
ParticipantDeviceState.Present -> {
isJoining.value = false
isInConference.value = true
updateWindowId(textureView)
}
else -> {}
}
}
override fun onStreamCapabilityChanged(
@ -105,14 +112,17 @@ class ConferenceParticipantDeviceData(
Log.i("[Conference Participant Device] Created device width Address [${participantDevice.address.asStringUriOnly()}], is it myself? $isMe")
participantDevice.addListener(listener)
activeSpeaker.value = false
micMuted.value = participantDevice.isMuted
isSpeaking.value = false
isMuted.value = participantDevice.isMuted
videoAvailable.value = participantDevice.getStreamAvailability(StreamType.Video)
val videoCapability = participantDevice.getStreamCapability(StreamType.Video)
isSendingVideo.value = videoCapability == MediaDirection.SendRecv || videoCapability == MediaDirection.SendOnly
isInConference.value = participantDevice.isInConference
val state = participantDevice.state
isJoining.value = state == ParticipantDeviceState.Joining || state == ParticipantDeviceState.Alerting
videoEnabled.value = isVideoAvailableAndSendReceive()
videoEnabled.addSource(videoAvailable) {
videoEnabled.value = isVideoAvailableAndSendReceive()
@ -121,7 +131,7 @@ class ConferenceParticipantDeviceData(
videoEnabled.value = isVideoAvailableAndSendReceive()
}
Log.i("[Conference Participant Device] Participant [${participantDevice.address.asStringUriOnly()}], is in conf? ${isInConference.value}, is video available? ${videoAvailable.value} ($videoCapability), is mic muted? ${micMuted.value}")
Log.i("[Conference Participant Device] Participant [${participantDevice.address.asStringUriOnly()}], is in conf? ${isInConference.value}, is video available? ${videoAvailable.value} ($videoCapability), is mic muted? ${isMuted.value}")
}
override fun destroy() {

View file

@ -124,17 +124,23 @@ class ConferenceViewModel : ViewModel() {
this@ConferenceViewModel.subject.value = subject
}
override fun onParticipantDeviceJoined(conference: Conference, device: ParticipantDevice) {
override fun onParticipantDeviceStateChanged(
conference: Conference,
device: ParticipantDevice,
state: ParticipantDeviceState
) {
if (conference.isMe(device.address)) {
Log.i("[Conference] Entered conference")
isConferenceLocallyPaused.value = false
}
}
override fun onParticipantDeviceLeft(conference: Conference, device: ParticipantDevice) {
if (conference.isMe(device.address)) {
Log.i("[Conference] Left conference")
isConferenceLocallyPaused.value = true
when (state) {
ParticipantDeviceState.Present -> {
Log.i("[Conference] Entered conference")
isConferenceLocallyPaused.value = false
}
ParticipantDeviceState.OnHold -> {
Log.i("[Conference] Left conference")
isConferenceLocallyPaused.value = true
}
else -> {}
}
}
}

View file

@ -34,7 +34,7 @@
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="@{controlsViewModel.folded || controlsViewModel.fullScreenMode ? @dimen/margin_0dp : conferenceViewModel.isRemotelyRecorded ? @dimen/voip_single_call_header_size_with_record_info : @dimen/voip_single_call_header_size, default=@dimen/voip_single_call_header_size}"/>
android:layout_marginTop="@{controlsViewModel.folded || controlsViewModel.fullScreenMode || controlsViewModel.pipMode ? @dimen/margin_0dp : conferenceViewModel.isRemotelyRecorded ? @dimen/voip_single_call_header_size_with_record_info : @dimen/voip_single_call_header_size, default=@dimen/voip_single_call_header_size}"/>
<androidx.constraintlayout.widget.Guideline
android:id="@+id/hinge_top"

View file

@ -34,7 +34,7 @@
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="@{controlsViewModel.folded ? @dimen/margin_0dp : conferenceViewModel.isRemotelyRecorded ? @dimen/voip_single_call_header_size_with_record_info : @dimen/voip_single_call_header_size, default=@dimen/voip_single_call_header_size}"/>
android:layout_marginTop="@{controlsViewModel.fullScreenMode || controlsViewModel.pipMode || controlsViewModel.folded ? @dimen/margin_0dp : conferenceViewModel.isRemotelyRecorded ? @dimen/voip_single_call_header_size_with_record_info : @dimen/voip_single_call_header_size, default=@dimen/voip_single_call_header_size}"/>
<androidx.constraintlayout.widget.Guideline
android:id="@+id/hinge_top"
@ -126,7 +126,6 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/hinge_bottom"
android:layout_marginTop="10dp"
android:onClick="@{() -> controlsViewModel.toggleFullScreen()}"
app:entries="@{conferenceViewModel.conferenceParticipantDevices}"
app:layout="@{@layout/voip_conference_participant_remote_grid}" />

View file

@ -34,7 +34,7 @@
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="@{controlsViewModel.folded || controlsViewModel.fullScreenMode ? @dimen/margin_0dp : conferenceViewModel.isRemotelyRecorded ? @dimen/voip_single_call_header_size_with_record_info : @dimen/voip_single_call_header_size, default=@dimen/voip_single_call_header_size}"/>
android:layout_marginTop="@{controlsViewModel.folded || controlsViewModel.fullScreenMode || controlsViewModel.pipMode ? @dimen/margin_0dp : conferenceViewModel.isRemotelyRecorded ? @dimen/voip_single_call_header_size_with_record_info : @dimen/voip_single_call_header_size, default=@dimen/voip_single_call_header_size}"/>
<androidx.constraintlayout.widget.Guideline
android:id="@+id/hinge_top"

View file

@ -34,7 +34,7 @@
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="@{controlsViewModel.folded ? @dimen/margin_0dp : conferenceViewModel.isRemotelyRecorded ? @dimen/voip_single_call_header_size_with_record_info : @dimen/voip_single_call_header_size, default=@dimen/voip_single_call_header_size}"/>
android:layout_marginTop="@{controlsViewModel.fullScreenMode || controlsViewModel.pipMode || controlsViewModel.folded ? @dimen/margin_0dp : conferenceViewModel.isRemotelyRecorded ? @dimen/voip_single_call_header_size_with_record_info : @dimen/voip_single_call_header_size, default=@dimen/voip_single_call_header_size}"/>
<androidx.constraintlayout.widget.Guideline
android:id="@+id/hinge_top"
@ -126,7 +126,6 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/hinge_bottom"
android:layout_marginTop="10dp"
android:onClick="@{() -> controlsViewModel.toggleFullScreen()}"
app:entries="@{conferenceViewModel.conferenceParticipantDevices}"
app:layout="@{@layout/voip_conference_participant_remote_grid}" />

View file

@ -15,14 +15,15 @@
android:layout_width="@dimen/voip_active_speaker_miniature_size"
android:layout_height="@dimen/voip_active_speaker_miniature_size"
android:layout_margin="5dp"
android:background="@{!data.isInConference ? @drawable/shape_remote_paused_background : data.videoEnabled ? @drawable/shape_remote_video_background : @drawable/shape_remote_background, default=@drawable/shape_remote_background}"
android:background="@{!data.isInConference &amp;&amp; !data.isJoining ? @drawable/shape_remote_paused_background : data.videoEnabled ? @drawable/shape_remote_video_background : @drawable/shape_remote_background, default=@drawable/shape_remote_background}"
app:layout_alignSelf="flex_end"
app:layout_flexShrink="0">
<ImageView
android:id="@+id/participant_avatar"
android:layout_width="@dimen/voip_conference_active_speaker_miniature_avatar_size"
android:layout_height="@dimen/voip_conference_active_speaker_miniature_avatar_size"
android:visibility="@{data.videoEnabled || !data.isInConference ? View.GONE : View.VISIBLE}"
android:visibility="@{data.isInConference || data.isJoining ? View.VISIBLE : View.GONE}"
android:contentDescription="@null"
coilVoipContact="@{data}"
app:layout_constraintBottom_toBottomOf="parent"
@ -44,12 +45,13 @@
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/paused"
android:layout_width="@dimen/voip_conference_active_speaker_miniature_avatar_size"
android:layout_height="@dimen/voip_conference_active_speaker_miniature_avatar_size"
android:background="@drawable/shape_button_background"
android:contentDescription="@string/content_description_participant_is_paused"
android:src="@drawable/icon_pause"
android:visibility="@{data.isInConference ? View.GONE : View.VISIBLE, default=gone}"
android:visibility="@{data.isInConference || data.isJoining ? View.GONE : View.VISIBLE, default=gone}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@ -71,7 +73,7 @@
android:layout_height="0dp"
android:contentDescription="@null"
android:src="@drawable/shape_conference_active_speaker_border"
android:visibility="@{data.activeSpeaker ? View.VISIBLE : View.GONE, default=gone}"
android:visibility="@{data.isSpeaking ? View.VISIBLE : View.GONE, default=gone}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
@ -90,16 +92,15 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<!--<TextView
android:visibility="@{data.isInConference ? View.GONE : View.VISIBLE, default=gone}"
android:text="@string/conference_participant_paused"
style="@style/call_remote_name_font"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/participant_name"/>-->
<ProgressBar
android:id="@+id/joining"
android:layout_width="@dimen/voip_conference_participant_joining_icon_size_active_speaker"
android:layout_height="@dimen/voip_conference_participant_joining_icon_size_active_speaker"
android:indeterminate="true"
android:indeterminateDrawable="@drawable/icon_spinner_rotating"
android:visibility="@{data.isJoining ? View.VISIBLE : View.GONE, default=gone}"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:layout_width="@dimen/voip_conference_participant_mic_muted_icon_size_active_speaker"
@ -109,7 +110,7 @@
android:contentDescription="@string/content_description_conference_participant_mic_muted"
android:padding="2dp"
android:src="@drawable/icon_mic_muted"
android:visibility="@{data.micMuted ? View.VISIBLE : View.GONE, default=gone}"
android:visibility="@{data.isMuted ? View.VISIBLE : View.GONE, default=gone}"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />

View file

@ -36,7 +36,7 @@
android:adjustViewBounds="true"
android:contentDescription="@null"
android:src="@drawable/shape_conference_audio_only_border"
android:visibility="@{data.activeSpeaker ? View.VISIBLE : View.GONE, default=gone}"
android:visibility="@{data.isSpeaking ? View.VISIBLE : View.GONE, default=gone}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@ -48,10 +48,10 @@
android:layout_height="@dimen/voip_conference_audio_only_participant_avatar_size"
android:layout_marginStart="10dp"
android:contentDescription="@null"
android:visibility="@{data.isInConference ? View.VISIBLE : View.GONE}"
android:visibility="@{data.isInConference || data.isJoining ? View.VISIBLE : View.GONE}"
coilVoipContact="@{data}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/paused_avatar"
app:layout_constraintEnd_toStartOf="@id/paused_avatar"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
@ -64,10 +64,10 @@
android:background="@drawable/shape_button_background"
android:contentDescription="@string/content_description_participant_is_paused"
android:src="@drawable/icon_pause"
android:visibility="@{data.isInConference ? View.GONE : View.VISIBLE, default=gone}"
android:visibility="@{data.isInConference || data.isJoining ? View.GONE : View.VISIBLE, default=gone}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/participant_name"
app:layout_constraintStart_toEndOf="@+id/participant_avatar"
app:layout_constraintEnd_toStartOf="@id/participant_name"
app:layout_constraintStart_toEndOf="@id/participant_avatar"
app:layout_constraintTop_toTopOf="parent" />
<TextView
@ -80,10 +80,29 @@
android:ellipsize="end"
android:gravity="center_vertical"
android:maxLines="2"
android:text="@{(data.contact.name ?? data.displayName) + (data.isInConference ? `` : ` ` + @string/conference_participant_paused), default=`Merry Brandybuck`}"
android:text="@{(data.contact.name ?? data.displayName) + (data.isInConference || data.isJoining ? `` : ` ` + @string/conference_participant_paused), default=`Merry Brandybuck`}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/participant_mic_muted"
app:layout_constraintStart_toEndOf="@+id/paused_avatar"
app:layout_constraintEnd_toStartOf="@id/endBarrier"
app:layout_constraintStart_toEndOf="@id/paused_avatar"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/endBarrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="left"
app:constraint_referenced_ids="joining, participant_mic_muted" />
<ProgressBar
android:id="@+id/joining"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:indeterminateDrawable="@drawable/icon_spinner_rotating"
android:visibility="@{data.isJoining ? View.VISIBLE : View.GONE, default=gone}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/participant_name"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
@ -95,10 +114,10 @@
android:contentDescription="@string/content_description_conference_participant_mic_muted"
android:padding="2dp"
android:src="@drawable/icon_mic_muted"
android:visibility="@{data.micMuted ? View.VISIBLE : View.GONE, default=gone}"
android:visibility="@{data.isMuted ? View.VISIBLE : View.GONE, default=gone}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/participant_name"
app:layout_constraintStart_toEndOf="@id/participant_name"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -20,18 +20,19 @@
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="5dp"
android:background="@{!data.isInConference ? @drawable/shape_remote_paused_background : data.videoEnabled ? @drawable/shape_remote_video_background : @drawable/shape_remote_background, default=@drawable/shape_remote_background}"
android:background="@{!data.isInConference &amp;&amp; !data.isJoining ? @drawable/shape_remote_paused_background : data.videoEnabled ? @drawable/shape_remote_video_background : @drawable/shape_remote_background, default=@drawable/shape_remote_background}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/participant_avatar"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="30dp"
android:contentDescription="@null"
android:visibility="@{data.videoEnabled || !data.isInConference ? View.GONE : View.VISIBLE}"
android:visibility="@{data.isInConference || data.isJoining ? View.VISIBLE : View.GONE}"
coilVoipContact="@{data}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
@ -55,12 +56,13 @@
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/paused"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_button_background"
android:contentDescription="@string/content_description_participant_is_paused"
android:src="@drawable/icon_pause"
android:visibility="@{data.isInConference ? View.GONE : View.VISIBLE, default=gone}"
android:visibility="@{data.isInConference || data.isJoining ? View.GONE : View.VISIBLE, default=gone}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@ -73,7 +75,7 @@
android:adjustViewBounds="true"
android:contentDescription="@null"
android:src="@drawable/shape_conference_active_speaker_border"
android:visibility="@{data.activeSpeaker ? View.VISIBLE : View.GONE, default=gone}"
android:visibility="@{data.isSpeaking ? View.VISIBLE : View.GONE, default=gone}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
@ -90,16 +92,6 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
style="@style/call_remote_name_font"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:text="@string/conference_participant_paused"
android:visibility="@{data.isInConference ? View.GONE : View.VISIBLE, default=gone}"
app:layout_constraintBottom_toBottomOf="@id/participant_name"
app:layout_constraintStart_toEndOf="@id/participant_name" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@ -112,6 +104,17 @@
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ProgressBar
android:id="@+id/joining"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:indeterminate="true"
android:indeterminateDrawable="@drawable/icon_spinner_rotating"
android:visibility="@{data.isJoining ? View.VISIBLE : View.GONE, default=gone}"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:layout_width="@dimen/voip_conference_participant_mic_muted_icon_size_grid"
android:layout_height="@dimen/voip_conference_participant_mic_muted_icon_size_grid"
@ -120,7 +123,7 @@
android:contentDescription="@string/content_description_conference_participant_mic_muted"
android:padding="2dp"
android:src="@drawable/icon_mic_muted"
android:visibility="@{data.micMuted ? View.VISIBLE : View.GONE, default=gone}"
android:visibility="@{data.isMuted ? View.VISIBLE : View.GONE, default=gone}"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />

View file

@ -59,7 +59,9 @@
<dimen name="voip_active_speaker_miniature_margin">10dp</dimen>
<dimen name="voip_conference_active_speaker_miniature_avatar_size">50dp</dimen>
<dimen name="voip_conference_participant_mic_muted_icon_size_grid">30dp</dimen>
<dimen name="voip_conference_participant_joining_icon_size_grid">30dp</dimen>
<dimen name="voip_conference_participant_mic_muted_icon_size_active_speaker">25dp</dimen>
<dimen name="voip_conference_participant_joining_icon_size_active_speaker">35dp</dimen>
<dimen name="voip_dialog_button_max_width">137dp</dimen>
<dimen name="voip_contact_avatar_max_size">180dp</dimen>
<dimen name="voip_contact_avatar_text_size">80sp</dimen>