Skip to main content
Version: 2.x.x

Change Mode - Flutter

In a live stream, audience members usually join in RECV_ONLY mode, meaning they can only view and listen to the hosts. However, if a host invites an audience member to actively participate (e.g., to speak or present), the audience member can switch their mode to SEND_AND_RECV using the changeMode() method.

This guide explains how to use the changeMode() method and walks through a sample implementation where a host invites an audience member to become a host using PubSub.

changeMode()​

  • The changeMode() method from the Room class allows a participant to switch between modes during a live stream—for example, from audience to host.
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class LivestreamScreen extends StatefulWidget {
const LivestreamScreen({Key? key}) : super(key: key);

@override
_LiveStreamScreenState createState() => _LiveStreamScreenState();
}

class _LiveStreamScreenState extends State<LiveStreamScreen> {
late Room _room;

@override
void initState() {
super.initState();
}

@override
Widget build(BuildContext context) {
return Column(children: [
ElevatedButton(
child: const Text('Change Mode'),
onPressed: () async {
if (_room.localParticipant.mode == Mode.SEND_AND_RECV) {
_room.changeMode(Mode.RECV_ONLY);// change mode to RECV_ONLY
} else if (_room.localParticipant.mode == Mode.RECV_ONLY) {
_room.changeMode(Mode.SEND_AND_RECV); // change Mode to SEND_AND_RECV
}
Navigator.pop(context);
},
),
]);
}
}

Implementation Guide​

Step 1 : Create a Pubsub Topic​

  • Set up a PubSub topic to send a mode change request from the host to a specific audience member.
void sendInvite(Room livestream, String participantId) {
livestream.pubSub.publish(
"REQUEST_TO_JOIN_AS_HOST_$participantId", // PubSub topic specific to participant
"SEND_AND_RECV", // message
);
}

Step 2 : Create an Invite Button​

  • Add an "Invite" button for each audience member. When clicked, it publishes a PubSub message with the mode "SEND_AND_RECV" to that participant.
Widget buildInviteButton(Room livestream, Participant participant) {
return Expanded(
child: ListView.builder(
itemCount: _participants.values.length,
itemBuilder: (context, index) => ParticipantListItem(
participant: _participants.values.elementAt(index),
isRaisedHand: raisedHandParticipant
.contains(_participants.values.elementAt(index).id),
onMoreOptionsSelected: (value) {
if (value == "Remove from Co-host" ||
value == "Add as a Co-host") {
sendInvite(widget.livestream.id,_participants.values.elementAt(index).id)

}
},
),
),
),
}

class ParticipantListItem extends StatefulWidget {
...
}

class _ParticipantListItemState extends State<ParticipantListItem> {
...
@override
Widget build(BuildContext context) {
return Column(
children: [
Container(
// padding: const EdgeInsets.all(12),
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
if (!widget.participant.isLocal)
PopupMenuButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12)),
color: black700,
icon: const Icon(
Icons.more_vert,
color: Colors.white,
),
onSelected: (value) {
widget.onMoreOptionsSelected(value);
},
itemBuilder: (context) {
return {
(widget.participant.mode == Mode.RECV_ONLY
? "Add as a Co-host"
: "Remove from Co-host"),
'Remove Participant'
}.map((String choice) {
return PopupMenuItem<String>(
value: choice,
child: Text(choice),
);
}).toList();
}),
],
),
),
],
);
}

void addParticipantListener(Participant participant) {
participant.on(Events.streamEnabled, (Stream _stream) {
if (mounted) {
setState(() {
if (_stream.kind == "video") {
videoStream = _stream;
} else if (_stream.kind == 'audio') {
audioStream = _stream;
}
});
}
});

participant.on(Events.streamDisabled, (Stream _stream) {
if (mounted) {
setState(() {
if (_stream.kind == "video") {
videoStream = null;
} else if (_stream.kind == 'audio') {
audioStream = null;
}
});
}
});
}
}


Step 3 : Create a Listener to Change the Mode​

  • On the audience side, subscribe to the specific PubSub topic. When a mode request is received, update the participant’s mode using changeMode().
void registerModeListener(Room livestream, BuildContext context) async {
await livestream.pubSub.subscribe(
"CHANGE_MODE_${livestream.localParticipant.id}",
(PubSubMessage pubSubMessage) {
final message = pubSubMessage.message;

if (message == "SEND_AND_RECV") {
showDialog(
context: context,
builder: (context) => AlertDialog(
content: Text(
"${pubSubMessage.senderName} requested you to join as a speaker",
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text("Decline"),
),
TextButton(
onPressed: () {
livestream.changeMode(Mode.SEND_AND_RECV);
Navigator.pop(context);
},
child: const Text("Accept"),
),
],
),
);
}
},
);
}

API Reference​

The API references for all the methods and events utilized in this guide are provided below.

Got a Question? Ask us on discord


Was this helpful?