Added support for screen sharing using new SDK APIs

This commit is contained in:
Sylvain Berfini 2024-03-04 11:12:07 +01:00
parent 719fa62752
commit 0fac6150c7
5 changed files with 89 additions and 18 deletions

View file

@ -61,6 +61,8 @@ class ConferenceModel {
val conferenceLayout = MutableLiveData<Int>()
val isScreenSharing = MutableLiveData<Boolean>()
val isPaused = MutableLiveData<Boolean>()
val isMeParticipantSendingVideo = MutableLiveData<Boolean>()
@ -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

View file

@ -51,6 +51,8 @@ class ConferenceParticipantDeviceModel @WorkerThread constructor(
val isActiveSpeaker = MutableLiveData<Boolean>()
val isScreenSharing = MutableLiveData<Boolean>()
val isVideoAvailable = MutableLiveData<Boolean>()
val isSendingVideo = MutableLiveData<Boolean>()
@ -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(

View file

@ -13,7 +13,7 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="@dimen/call_conference_active_speaker_miniature_size"
android:layout_height="@dimen/call_conference_active_speaker_miniature_size"
android:visibility="@{model.isActiveSpeaker ? View.GONE : View.VISIBLE}"
android:visibility="@{model.isActiveSpeaker &amp;&amp; !model.isScreenSharing ? View.GONE : View.VISIBLE}"
android:padding="2dp">
<ImageView

View file

@ -4,6 +4,7 @@
<data>
<import type="android.view.View" />
<import type="org.linphone.ui.call.model.ConferenceModel" />
<variable
name="gridClickListener"
type="View.OnClickListener" />
@ -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() &lt; 7, default=false}"
android:checked="@{viewModel.conferenceLayout == 0}"
android:enabled="@{viewModel.participantDevices.size() &lt; 7 &amp;&amp; !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"/>

View file

@ -40,7 +40,7 @@
<string name="notification_channel_missed_call_name">&appName; notifications d\'appels manqués</string>
<string name="notification_channel_service_name">&appName; notification de service</string>
<string name="notification_channel_chat_name">&appName; notifications des conversations</string>
<string name="notification_chat_message_reaction_received">%s a réagi à %s par : %s</string>
<string name="notification_chat_message_reaction_received">%s a réagi par %s à : %s</string>
<string name="notification_mark_message_as_read">Marquer comme lu</string>
<string name="notification_reply_to_message">Répondre</string>
<string name="notification_missed_call">Appel manqué de %s</string>