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 theRoom
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