No longer use conferenceScheduler for creating group calls

This commit is contained in:
Sylvain Berfini 2025-01-16 15:30:56 +01:00
parent 4dd92cddf0
commit f5ba48b9f0
6 changed files with 105 additions and 159 deletions

View file

@ -228,12 +228,20 @@ class CallsViewModel
AppUtils.getString(R.string.conference_locally_hosted_title)
}
val params = core.createConferenceParams(null)
params.subject = subject
// Prevent group call to start in audio only layout
params.isVideoEnabled = true
val conference = core.createConferenceWithParams(params)
conference?.addParticipants(core.calls)
val conference = LinphoneUtils.createGroupCall(defaultAccount, subject)
if (conference == null) {
Log.e("$TAG Failed to create conference!")
showRedToastEvent.postValue(
Event(
Pair(
R.string.conference_failed_to_merge_calls_into_conference_toast,
R.drawable.warning_circle
)
)
)
} else {
conference.addParticipants(core.calls)
}
}
}

View file

@ -28,14 +28,9 @@ import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.R
import org.linphone.core.Address
import org.linphone.core.ChatRoom
import org.linphone.core.Conference
import org.linphone.core.ConferenceParams
import org.linphone.core.ConferenceScheduler
import org.linphone.core.ConferenceSchedulerListenerStub
import org.linphone.core.Factory
import org.linphone.core.Participant
import org.linphone.core.ParticipantInfo
import org.linphone.core.StreamType
import org.linphone.core.MediaDirection
import org.linphone.core.tools.Log
import org.linphone.ui.GenericViewModel
import org.linphone.utils.Event
@ -64,47 +59,6 @@ abstract class AbstractConversationViewModel : GenericViewModel() {
return ::chatRoom.isInitialized
}
private val conferenceSchedulerListener = object : ConferenceSchedulerListenerStub() {
override fun onStateChanged(
conferenceScheduler: ConferenceScheduler,
state: ConferenceScheduler.State
) {
Log.i("$TAG Conference scheduler state is $state")
if (state == ConferenceScheduler.State.Ready) {
conferenceScheduler.removeListener(this)
val conferenceAddress = conferenceScheduler.info?.uri
if (conferenceAddress != null) {
Log.i(
"$TAG Conference info created, address is ${conferenceAddress.asStringUriOnly()}"
)
coreContext.startVideoCall(conferenceAddress)
} else {
Log.e("$TAG Conference info URI is null!")
showRedToastEvent.postValue(
Event(
Pair(
R.string.conference_failed_to_create_group_call_toast,
R.drawable.warning_circle
)
)
)
}
} else if (state == ConferenceScheduler.State.Error) {
conferenceScheduler.removeListener(this)
Log.e("$TAG Failed to create group call!")
showRedToastEvent.postValue(
Event(
Pair(
R.string.conference_failed_to_create_group_call_toast,
R.drawable.warning_circle
)
)
)
}
}
}
@WorkerThread
open fun beforeNotifyingChatRoomFound(sameOne: Boolean) {
}
@ -216,41 +170,44 @@ abstract class AbstractConversationViewModel : GenericViewModel() {
return@postOnCoreThread
}
val conferenceInfo = Factory.instance().createConferenceInfo()
conferenceInfo.organizer = account.params.identityAddress
conferenceInfo.subject = chatRoom.subject
// Allows to have a chat room within the conference
conferenceInfo.setCapability(StreamType.Text, true)
// Enable end-to-end encryption if client supports it
conferenceInfo.securityLevel = if (LinphoneUtils.isEndToEndEncryptedChatAvailable(core)) {
Log.i("$TAG Requesting EndToEnd security level for conference")
Conference.SecurityLevel.EndToEnd
} else {
Log.i("$TAG Requesting PointToPoint security level for conference")
Conference.SecurityLevel.PointToPoint
val conference = LinphoneUtils.createGroupCall(account, chatRoom.subject.orEmpty())
if (conference == null) {
Log.e("$TAG Failed to create group call!")
showRedToastEvent.postValue(
Event(
Pair(
R.string.conference_failed_to_create_group_call_toast,
R.drawable.warning_circle
)
)
)
return@postOnCoreThread
}
val participants = arrayOfNulls<ParticipantInfo>(chatRoom.participants.size)
val callParams = core.createCallParams(null)
callParams?.isVideoEnabled = true
callParams?.videoDirection = MediaDirection.RecvOnly
val participants = arrayOfNulls<Address>(chatRoom.participants.size)
var index = 0
for (participant in chatRoom.participants) {
val info = Factory.instance().createParticipantInfo(participant.address)
// For meetings, all participants must have Speaker role
info?.role = Participant.Role.Speaker
participants[index] = info
participants[index] = participant.address
index += 1
}
conferenceInfo.setParticipantInfos(participants)
Log.i(
"$TAG Creating group call with subject ${conferenceInfo.subject} and ${participants.size} participant(s)"
"$TAG Inviting ${participants.size} participant(s) into newly created conference"
)
val conferenceScheduler = LinphoneUtils.createConferenceScheduler(account)
conferenceScheduler.addListener(conferenceSchedulerListener)
conferenceScheduler.account = account
// Will trigger the conference creation/update automatically
conferenceScheduler.info = conferenceInfo
if (conference.inviteParticipants(participants, callParams) != 0) {
Log.e("$TAG Failed to invite participants into group call!")
showRedToastEvent.postValue(
Event(
Pair(
R.string.conference_failed_to_create_group_call_toast,
R.drawable.warning_circle
)
)
)
}
}
}
}

View file

@ -28,13 +28,8 @@ import kotlinx.coroutines.launch
import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.LinphoneApplication.Companion.corePreferences
import org.linphone.R
import org.linphone.core.Conference
import org.linphone.core.ConferenceScheduler
import org.linphone.core.ConferenceSchedulerListenerStub
import org.linphone.core.Factory
import org.linphone.core.Participant
import org.linphone.core.ParticipantInfo
import org.linphone.core.StreamType
import org.linphone.core.Address
import org.linphone.core.MediaDirection
import org.linphone.core.tools.Log
import org.linphone.ui.main.history.model.NumpadModel
import org.linphone.ui.main.viewmodel.AddressSelectionViewModel
@ -82,50 +77,6 @@ class StartCallViewModel
MutableLiveData<Event<Boolean>>()
}
private val conferenceSchedulerListener = object : ConferenceSchedulerListenerStub() {
override fun onStateChanged(
conferenceScheduler: ConferenceScheduler,
state: ConferenceScheduler.State
) {
Log.i("$TAG Conference scheduler state is $state")
if (state == ConferenceScheduler.State.Ready) {
conferenceScheduler.removeListener(this)
val conferenceAddress = conferenceScheduler.info?.uri
if (conferenceAddress != null) {
Log.i(
"$TAG Conference info created, address is ${conferenceAddress.asStringUriOnly()}"
)
coreContext.startVideoCall(conferenceAddress)
leaveFragmentEvent.postValue(Event(true))
} else {
Log.e("$TAG Conference info URI is null!")
showRedToastEvent.postValue(
Event(
Pair(
R.string.conference_failed_to_create_group_call_toast,
R.drawable.warning_circle
)
)
)
}
operationInProgress.postValue(false)
} else if (state == ConferenceScheduler.State.Error) {
conferenceScheduler.removeListener(this)
Log.e("$TAG Failed to create group call!")
showRedToastEvent.postValue(
Event(
Pair(
R.string.conference_failed_to_create_group_call_toast,
R.drawable.warning_circle
)
)
)
operationInProgress.postValue(false)
}
}
}
init {
isNumpadVisible.value = false
numpadModel = NumpadModel(
@ -217,44 +168,48 @@ class StartCallViewModel
)
return@postOnCoreThread
}
operationInProgress.postValue(true)
val conferenceInfo = Factory.instance().createConferenceInfo()
conferenceInfo.organizer = account.params.identityAddress
conferenceInfo.subject = subject.value
// Allows to have a chat room within the conference
conferenceInfo.setCapability(StreamType.Text, true)
// Enable end-to-end encryption if client supports it
conferenceInfo.securityLevel = if (LinphoneUtils.isEndToEndEncryptedChatAvailable(core)) {
Log.i("$TAG Requesting EndToEnd security level for conference")
Conference.SecurityLevel.EndToEnd
} else {
Log.i("$TAG Requesting PointToPoint security level for conference")
Conference.SecurityLevel.PointToPoint
Log.i("$TAG Creating group call with subject ${subject.value}")
val conference = LinphoneUtils.createGroupCall(account, subject.value.orEmpty())
if (conference == null) {
Log.e("$TAG Failed to create group call!")
showRedToastEvent.postValue(
Event(
Pair(
R.string.conference_failed_to_create_group_call_toast,
R.drawable.warning_circle
)
)
)
return@postOnCoreThread
}
val participants = arrayOfNulls<ParticipantInfo>(selection.value.orEmpty().size)
val callParams = core.createCallParams(null)
callParams?.isVideoEnabled = true
callParams?.videoDirection = MediaDirection.RecvOnly
val participants = arrayOfNulls<Address>(selection.value.orEmpty().size)
var index = 0
for (participant in selection.value.orEmpty()) {
val info = Factory.instance().createParticipantInfo(participant.address)
// For meetings, all participants must have Speaker role
info?.role = Participant.Role.Speaker
participants[index] = info
participants[index] = participant.address
index += 1
}
conferenceInfo.setParticipantInfos(participants)
Log.i(
"$TAG Creating group call with subject ${subject.value} and ${participants.size} participant(s)"
"$TAG Inviting ${participants.size} participant(s) into newly created conference"
)
val conferenceScheduler = LinphoneUtils.createConferenceScheduler(account)
conferenceScheduler.addListener(conferenceSchedulerListener)
conferenceScheduler.account = account
// Will trigger the conference creation/update automatically
conferenceScheduler.info = conferenceInfo
if (conference.inviteParticipants(participants, callParams) != 0) {
Log.e("$TAG Failed to invite participants into group call!")
showRedToastEvent.postValue(
Event(
Pair(
R.string.conference_failed_to_create_group_call_toast,
R.drawable.warning_circle
)
)
)
}
operationInProgress.postValue(false)
}
}
}

View file

@ -263,6 +263,30 @@ class LinphoneUtils {
)
}
@WorkerThread
fun createGroupCall(account: Account?, subject: String): Conference? {
val core = coreContext.core
val conferenceParams = core.createConferenceParams(null)
conferenceParams.isVideoEnabled = true
conferenceParams.account = account
conferenceParams.subject = subject
// Enable end-to-end encryption if client supports it
conferenceParams.securityLevel = if (isEndToEndEncryptedChatAvailable(core)) {
Log.i("$TAG Requesting EndToEnd security level for conference")
Conference.SecurityLevel.EndToEnd
} else {
Log.i("$TAG Requesting PointToPoint security level for conference")
Conference.SecurityLevel.PointToPoint
}
// Allows to have a chat room within the conference
conferenceParams.isChatEnabled = true
Log.i("$TAG Creating group call with subject ${conferenceParams.subject}")
return core.createConferenceWithParams(conferenceParams)
}
@WorkerThread
fun getChatRoomParamsToCancelMeeting(): ConferenceParams? {
val chatRoomParams = coreContext.core.createConferenceParams(null)

View file

@ -697,6 +697,7 @@
<string name="conference_action_screen_sharing">Partage d\'écran</string>
<string name="conference_action_show_participants">Participants</string>
<string name="conference_failed_to_create_group_call_toast">Echec de l\'appel de groupe</string>
<string name="conference_failed_to_merge_calls_into_conference_toast">Echec de la fusion des appels</string>
<plurals name="conference_participants_list_title" tools:ignore="MissingQuantity">
<item quantity="one">%s participant</item>
<item quantity="other">%s participants</item>

View file

@ -737,6 +737,7 @@
<string name="conference_action_screen_sharing">Screen share</string>
<string name="conference_action_show_participants">Participants</string>
<string name="conference_failed_to_create_group_call_toast">Failed to create a group call!</string>
<string name="conference_failed_to_merge_calls_into_conference_toast">Failed to merge call!</string>
<plurals name="conference_participants_list_title">
<item quantity="one">%s participant</item>
<item quantity="other">%s participants</item>