diff --git a/app/src/main/java/org/linphone/ui/call/model/ConferenceModel.kt b/app/src/main/java/org/linphone/ui/call/model/ConferenceModel.kt index bad97e4e8..c1c99b100 100644 --- a/app/src/main/java/org/linphone/ui/call/model/ConferenceModel.kt +++ b/app/src/main/java/org/linphone/ui/call/model/ConferenceModel.kt @@ -61,6 +61,8 @@ class ConferenceModel { val conferenceLayout = MutableLiveData() + val isScreenSharing = MutableLiveData() + val isPaused = MutableLiveData() val isMeParticipantSendingVideo = MutableLiveData() @@ -88,6 +90,7 @@ class ConferenceModel { removeParticipant(participant) } + @WorkerThread override fun onParticipantDeviceMediaCapabilityChanged( conference: Conference, device: ParticipantDevice @@ -170,6 +173,32 @@ class ConferenceModel { ) } + @WorkerThread + override fun onParticipantDeviceScreenSharingChanged( + conference: Conference, + device: ParticipantDevice, + enabled: Boolean + ) { + Log.i( + "$TAG Participant device [${device.address.asStringUriOnly()}] is ${if (enabled) "sharing it's screen" else "no longer sharing it's screen"}" + ) + isScreenSharing.postValue(enabled) + if (enabled) { + val call = conference.call + if (call != null) { + val currentLayout = getCurrentLayout(call) + if (currentLayout == GRID_LAYOUT) { + Log.w( + "$TAG Current layout is mosaic but screen sharing was enabled, switching to active speaker layout" + ) + setNewLayout(ACTIVE_SPEAKER_LAYOUT) + } + } else { + Log.e("$TAG Screen sharing was enabled but conference's call is null!") + } + } + } + @WorkerThread override fun onStateChanged(conference: Conference, state: Conference.State) { Log.i("$TAG State changed [$state]") @@ -199,6 +228,8 @@ class ConferenceModel { conference = conf conference.addListener(conferenceListener) isPaused.postValue(conference.isIn) + val screenSharing = conference.screenSharingParticipant != null + isScreenSharing.postValue(screenSharing) Log.i( "$TAG Configuring conference with subject [${conference.subject}] from call [${call.callLog.callId}]" @@ -212,6 +243,12 @@ class ConferenceModel { val currentLayout = getCurrentLayout(call) conferenceLayout.postValue(currentLayout) + if (currentLayout == GRID_LAYOUT && screenSharing) { + Log.w( + "$TAG Conference has a participant sharing it's screen, changing layout from mosaic to active speaker" + ) + setNewLayout(ACTIVE_SPEAKER_LAYOUT) + } } @UiThread diff --git a/app/src/main/java/org/linphone/ui/call/model/ConferenceParticipantDeviceModel.kt b/app/src/main/java/org/linphone/ui/call/model/ConferenceParticipantDeviceModel.kt index d3451b74d..079fb7b7a 100644 --- a/app/src/main/java/org/linphone/ui/call/model/ConferenceParticipantDeviceModel.kt +++ b/app/src/main/java/org/linphone/ui/call/model/ConferenceParticipantDeviceModel.kt @@ -51,6 +51,8 @@ class ConferenceParticipantDeviceModel @WorkerThread constructor( val isActiveSpeaker = MutableLiveData() + val isScreenSharing = MutableLiveData() + val isVideoAvailable = MutableLiveData() val isSendingVideo = MutableLiveData() @@ -110,12 +112,9 @@ class ConferenceParticipantDeviceModel @WorkerThread constructor( available: Boolean, streamType: StreamType? ) { - Log.i( + Log.d( "$TAG Participant device [${participantDevice.address.asStringUriOnly()}] stream [$streamType] availability changed to ${if (available) "available" else "not available"}" ) - if (streamType == StreamType.Video) { - isVideoAvailable.postValue(available) - } } @WorkerThread @@ -124,15 +123,43 @@ class ConferenceParticipantDeviceModel @WorkerThread constructor( direction: MediaDirection?, streamType: StreamType? ) { - Log.i( + Log.d( "$TAG Participant device [${participantDevice.address.asStringUriOnly()}] stream [$streamType] capability changed to [$direction]" ) - if (streamType == StreamType.Video) { - val sending = direction == MediaDirection.SendRecv || direction == MediaDirection.SendOnly - isSendingVideo.postValue( - sending - ) - } + } + + @WorkerThread + override fun onScreenSharingChanged( + participantDevice: ParticipantDevice, + screenSharing: Boolean + ) { + Log.i( + "$TAG Participant device [${participantDevice.address.asStringUriOnly()}] is ${if (screenSharing) "sharing it's screen" else "no longer sharing it's screen"}" + ) + isScreenSharing.postValue(screenSharing) + } + + @WorkerThread + override fun onThumbnailStreamAvailabilityChanged( + participantDevice: ParticipantDevice, + available: Boolean + ) { + Log.i( + "$TAG Participant device [${participantDevice.address.asStringUriOnly()}] thumbnail availability changed to ${if (available) "available" else "not available"}" + ) + isVideoAvailable.postValue(available) + } + + @WorkerThread + override fun onThumbnailStreamCapabilityChanged( + participantDevice: ParticipantDevice, + direction: MediaDirection? + ) { + Log.i( + "$TAG Participant device [${participantDevice.address.asStringUriOnly()}] thumbnail capability changed to [$direction]" + ) + val sending = direction == MediaDirection.SendRecv || direction == MediaDirection.SendOnly + isSendingVideo.postValue(sending) } } @@ -156,11 +183,17 @@ class ConferenceParticipantDeviceModel @WorkerThread constructor( isMuted.postValue(device.isMuted) isSpeaking.postValue(device.isSpeaking) - isActiveSpeaker.postValue(false) Log.i( "$TAG Participant [${device.address.asStringUriOnly()}] is in state [${device.state}]" ) + isActiveSpeaker.postValue(false) + val screenSharing = device.isScreenSharingEnabled + isScreenSharing.postValue(screenSharing) + if (screenSharing) { + Log.i("$TAG Participant [${device.address.asStringUriOnly()}] is sharing it's screen") + } + isVideoAvailable.postValue(device.getStreamAvailability(StreamType.Video)) val videoCapability = device.getStreamCapability(StreamType.Video) isSendingVideo.postValue( diff --git a/app/src/main/res/layout/call_conference_active_speaker_cell.xml b/app/src/main/res/layout/call_conference_active_speaker_cell.xml index fc8dabb75..8e111ce48 100644 --- a/app/src/main/res/layout/call_conference_active_speaker_cell.xml +++ b/app/src/main/res/layout/call_conference_active_speaker_cell.xml @@ -13,7 +13,7 @@ + @@ -37,8 +38,8 @@ android:layout_marginBottom="1dp" android:drawableEnd="@drawable/squares_four" android:drawableTint="@color/in_call_label_color" - android:enabled="@{viewModel.participantDevices.size() < 7, default=false}" - android:checked="@{viewModel.conferenceLayout == 0}" + android:enabled="@{viewModel.participantDevices.size() < 7 && !viewModel.isScreenSharing, default=false}" + android:checked="@{viewModel.conferenceLayout == ConferenceModel.GRID_LAYOUT}" app:useMaterialThemeColors="false" app:buttonTint="@color/in_call_label_color"/> @@ -55,7 +56,7 @@ android:layout_marginBottom="1dp" android:drawableEnd="@drawable/picture_in_picture" android:drawableTint="@color/white" - android:checked="@{viewModel.conferenceLayout == 1}" + android:checked="@{viewModel.conferenceLayout == ConferenceModel.ACTIVE_SPEAKER_LAYOUT}" app:useMaterialThemeColors="false" app:buttonTint="@color/white"/> @@ -72,7 +73,7 @@ android:layout_marginBottom="1dp" android:drawableEnd="@drawable/waveform" android:drawableTint="@color/white" - android:checked="@{viewModel.conferenceLayout == -1}" + android:checked="@{viewModel.conferenceLayout == ConferenceModel.AUDIO_ONLY_LAYOUT}" app:useMaterialThemeColors="false" app:buttonTint="@color/white"/> diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 9d8a011c0..405f24f41 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -40,7 +40,7 @@ &appName; notifications d\'appels manqués &appName; notification de service &appName; notifications des conversations - %s a réagi à %s par : %s + %s a réagi par %s à : %s Marquer comme lu Répondre Appel manqué de %s