One common source of confusion in the conferencing APIs in UCMA has to do with getting information on the conference participants. If you look at the various classes that come into play when you are dealing with a conference, there are not one, not two, but FOUR different ways (methods or properties) to get a list of remote participants. See if you can think of them before reading on.
Here they are:
- Call.RemoteEndpoint property
- Conversation.RemoteParticipants property
- ConferenceSession.GetRemoteParticipantEndpoints method
- McuSession.GetRemoteParticipantEndpoints method
To muddle things further, if your application is joined to, for example, an audio conference, each of these will give you a different list. There are also corresponding events, such as Conversation.RemoteParticipantAttendanceChanged, and McuSession.ParticipantEndpointAttendanceChanged, and each will be invoked under different circumstances. This post goes through some of the reasons for these differences, and how you can tell which of the options to use for looking up remote participants.
ConversationParticipant and ParticipantEndpoint
The first thing I want to point out is that there are two different classes you may see representing remote participants in a conference or conversation. These two classes are ConversationParticipant and ParticipantEndpoint, and they have somewhat different purposes.
ConversationParticipant represents the user who is participating. If you look at the Uri property on a ConversationParticipant object, it will generally be an ordinary SIP URI in the form user@domain. ParticipantEndpoint, on the other hand, represents the specific endpoint that the user is using to participate in the conversation. A user might be active on several devices; this object identifies the individual device. If you look at the Uri property on a ParticipantEndpoint object, you will likely see a GRUU that belongs to the endpoint in question.
The Conversation.RemoteParticipants property gives a collection of ConversationParticipant objects; all of the others in the list give ParticipantEndpoint objects.
Call participants and conversation participants
The Call object, unlike the others, only gives you a single remote endpoint. Why is this?
The Conversation class tries to abstract away some of the differences between two-party and multi-party conversations. Because of this, you can use the same RemoteParticipants property to get information on other participants whether the conversation is a two-party call or a conference. In reality, though, when your application participates in a conference it is actually talking to the conference focus (for SIP signaling) and the MCU (for media), not directly to the other participants. The Call object, which always represents a signaling session between two endpoints, reveals this. If you look at the RemoteEndpoint property on the Call object that is associated with a conference, you will see a ParticipantEndpoint object with a URI like this:
That is the SIP URI of the audio/video MCU, which is the "real" participant on the other end of this call.
Conference participants vs. MCU participants
One other important distinction is between the participants listed by the ConferenceSession object and the participants listed by the McuSession object.
If you look at conference participants through the GetRemoteParticipantEndpoints method or the ParticipantEndpointAttendanceChanged event on the ConferenceSession object, you will see participants who have joined the conference focus, whether or not they are dialed in to any MCUs. If you look at the Lync client, on the conversation window there are little icons for each modality next to the names of the participants.
For a participant who has not joined any MCUs, all of these icons will be grey. Each icon that has solid black outlines indicates that the participant has dialed in to the MCU for that modality (e.g., audio in the case of the phone).
So, if you use the ConferenceSession.ParticipantEndpointAttendanceChanged event, you will get a notification when a participant first connects to the conference focus and is added to the roster. If, on the other hand, you use the AudioVideoMcuSession.ParticipantEndpointAttendanceChanged event, you will only get notifications when a participant actually dials in to the audio/video MCU, which may be a few seconds after that participant joins the conference focus, or maybe never if that participant sticks to other modalities.
The same applies for participants who are leaving a conference. In the Lync client, you can leave the A/V MCU without disconnecting from the conference focus by clicking the icon of a phone with an X on the conversation window. This will cause you to be removed from the collection of participant endpoints for the AudioVideoMcuSession, but not from the collection that belongs to the ConferenceSession object.
When monitoring participants in a conference, make sure you are looking in the right place and using the methods or events that match what you are trying to get. Otherwise you may get unexpected behaviour from your application.