2020 API AWARDS WINNER - BEST IN MEDIA APIs LEARN MORE

Manage Participants

This tutorial is a part of a series; it comes after Integrate video.

You have a basic video conference application with which you can video call your friends using a conference room. However, you do not control the conference nor have any information about the conference participants.

This tutorial will take you through some simple steps to follow to have a full participants’ list with the possibility to mute and unmute them.

Note: If you want to skip this tutorial, you can get full access to the source code at the end of it.

Step 1: Create the participants’ list

Note: The participants’ list is only visible when the user has joined the conference.

  • JavaScript
  • Swift
  • Java

Open the index.html file and add a div with the id participants and a ul with the id participants-list in join-panel, right after the actions div:

```html
<div id="actions">...</div>
<!-- Add participants div just after actions div -->
<div id="participants">
    <h3>Participants</h3>
    <ul id="participants-list"></ul>
</div>
...

Add UI for showing participants in ViewController.swift.

1. In ViewController.swift, add a variable to the ViewController class to refer to the user interface element that will be created in step 2.

class ViewController: UIViewController {
    ...

    // Participant label.
    var participantsLabel: UILabel!

    ...
}

2. Modify initConferenceUI to extend the user interface and clear participantsLabel when the conference is left.

...

func initConferenceUI() {
    ...

    // Participants label.
    participantsLabel = UILabel(frame: CGRect(x: 100, y: videosView1.frame.origin.y + videosView1.frame.height + 16, width: 200, height: 30))
    participantsLabel.backgroundColor = .lightGray
    participantsLabel.adjustsFontSizeToFitWidth = true
    participantsLabel.minimumScaleFactor = 0.1
    self.view.addSubview(participantsLabel)
}

...

@objc func leaveButtonAction(sender: UIButton!) {
    VoxeetSDK.shared.conference.leave { error in

        ...
        self.participantsLabel.text = nil /* Reset participants label */

    }
}

...

Layout modification

1. To modify the layout, edit the main_activity.xml file, adding the following content for Step 4:

<LinearLayout ...>
    ...

    <!-- Step 4. Put the layout changes for the view participants step here -->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="users :" />

    <EditText
        android:id="@+id/participants"
        android:enabled="false"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <!-- Step 5. ...

</LinearLayout>

2. Modify the interface linking in the MainActivity class in MainActivity.java:

  • New field for MainActivity:
@Bind(R.id.participants)
EditText participants;
  • New method for MainActivity:
public void updateParticipants() {

}

3. Add the following logic to the application:

  • Use the following implementation for updateParticipants.
public void updateParticipants() {
    List<Participant> participantsList = VoxeetSDK.conference().getParticipants();
    List<String> names = new ArrayList<>();

    for (Participant participant : participantsList) {
        if (participant.streams().size() > 0)
            names.add(participant.getInfo().getName());
    }

    participants.setText(TextUtils.join(", ", names));
}

Step 2: Add a participant to the list

Note: The participants’ list is updated upon receiving the participantJoined and participantLeft events, the same way the participants’ streams were added in the previous tutorial.

  • JavaScript
  • Swift
  • Java

Open the ui.js file and create a function named addParticipantNode that will add the participant’s name to the participants-list element.

const addParticipantNode = participant => {
  const participantsList = document.getElementById("participants-list")

  // if the participant is the current session user, don’t add himself to the list
  if (participant.id === VoxeetSDK.session.participant.id) return

  let participantNode = document.createElement("li")
  participantNode.setAttribute("id", "participant-" + participant.id)
  participantNode.innerText = `${participant.info.name}`

  participantsList.appendChild(participantNode)
}

Then, open client.js file and call the addParticipantNode upon receiving the streamAdded event.

    VoxeetSDK.conference.on("streamAdded", (participant, stream) => {
        ...
        // Call addParticipantNode here
        addParticipantNode(participant)
    })

1. Add a method for updating the participants list to the VTConferenceDelegate extension in ViewController.swift.

...

extension ViewController: VTConferenceDelegate {
    ...

    func updateParticipantsLabel() {
        // Update participants label.
        let participants = VoxeetSDK.shared.conference.current?.participants
            .filter({ $0.streams.isEmpty == false }) /* Gets only participants with stream */
        let usernames = participants?.map({ $0.info.name ?? "" })
        participantsLabel.text = usernames?.joined(separator: ", ")
    }
}

2. When a participant joins the conference, the application calls the streamAdded event which calls streamUpdated event. In streamUpdated, call updateParticipantsLabel to update the participants list.

...

extension ViewController: VTConferenceDelegate {
    ...

    func streamUpdated(participant: VTParticipant, stream: MediaStream) {
        ...

        // Update participants label.
        updateParticipantsLabel()
    }
}

1. Add the following logic to the application:

  • Add a handler for the ParticipantAddedEvent.
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(ParticipantAddedEvent event) {
    updateParticipants();
}

Step 3: Remove a participant from the list

  • JavaScript
  • Swift
  • Java

Open the ui.js file and create a function named removeParticipantNode that removes child nodes of the participants-list based on the participant ID:

const removeParticipantNode = participant => {
    let participantNode = document.getElementById("participant-" + participant.id)

    if (participantNode) {
        participantNode.parentNode.removeChild(participantNode)
    }
}

Then, open client.js file and update the streamRemoved handler by calling the removeParticipantNode:

const main = () => {
    /* Events handlers */
    ...
    VoxeetSDK.conference.on('streamRemoved', (participant, stream) => {
        ...
        removeParticipantNode(participant);
    });
};

1. When a participant leaves the conference, the conference delegate’s method streamRemoved is called. In that method, call updateParticipantsLabel to remove that participant from the participants list.

...

extension ViewController: VTConferenceDelegate {
    ...

    func streamRemoved(participant: VTParticipant, stream: MediaStream) {
        updateParticipantsLabel()
    }
}

1. Add the following logic to the application:

  • Add a handler for the ParticipantUpdatedEvent.
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(ParticipantUpdatedEvent event) {
    updateParticipants();
}

What’s next?

If you want to learn more about creating conference applications, go to the Implement screen sharing tutorial.