Participant ChangeNotifier

This commit is contained in:
David Zhao
2021-07-25 22:22:11 -07:00
parent a47c50c3c1
commit d193b9fb7f
6 changed files with 70 additions and 5 deletions
+5 -2
View File
@@ -56,6 +56,7 @@ class LocalParticipant extends Participant {
var pub = new LocalTrackPublication(trackInfo, track, this); var pub = new LocalTrackPublication(trackInfo, track, this);
addTrackPublication(pub); addTrackPublication(pub);
notifyListeners();
return pub; return pub;
} }
@@ -83,15 +84,17 @@ class LocalParticipant extends Participant {
var pub = new LocalTrackPublication(trackInfo, track, this); var pub = new LocalTrackPublication(trackInfo, track, this);
addTrackPublication(pub); addTrackPublication(pub);
notifyListeners();
return pub; return pub;
} }
unpublishTrack(Track track) { unpublishTrack(Track track) {
var pub = tracks.values.firstWhere((element) => element.track == track); var existing = tracks.values.where((element) => element.track == track);
if (pub == null) { if (existing.isEmpty) {
return; return;
} }
var pub = existing.first;
track.stop(); track.stop();
var sender = track.transceiver?.sender; var sender = track.transceiver?.sender;
+43 -1
View File
@@ -1,3 +1,5 @@
import 'package:flutter/foundation.dart';
import 'remote_participant.dart'; import 'remote_participant.dart';
import '../proto/livekit_models.pb.dart'; import '../proto/livekit_models.pb.dart';
import '../track/remote_track_publication.dart'; import '../track/remote_track_publication.dart';
@@ -22,7 +24,14 @@ mixin ParticipantDelegate {
RemoteParticipant participant, String sid, String? message) {} RemoteParticipant participant, String sid, String? message) {}
} }
class Participant { /// Represents a Participant in the room, notifies changes via delegates as
/// well as ChangeNotifier/providers.
/// A change notification is triggered when
/// - speaking status changed
/// - mute status changed
/// - added/removed subscribed tracks
/// - metadata changed
class Participant extends ChangeNotifier {
Map<String, TrackPublication> audioTracks = {}; Map<String, TrackPublication> audioTracks = {};
Map<String, TrackPublication> videoTracks = {}; Map<String, TrackPublication> videoTracks = {};
@@ -45,11 +54,14 @@ class Participant {
DateTime? lastSpokeAt; DateTime? lastSpokeAt;
ParticipantDelegate? roomDelegate; ParticipantDelegate? roomDelegate;
/// delegate to receive participant callbacks
ParticipantDelegate? delegate; ParticipantDelegate? delegate;
ParticipantInfo? _participantInfo; ParticipantInfo? _participantInfo;
bool _isSpeaking = false; bool _isSpeaking = false;
/// when the participant joined the room
DateTime get joinedAt { DateTime get joinedAt {
var pi = _participantInfo; var pi = _participantInfo;
if (pi != null) { if (pi != null) {
@@ -62,6 +74,30 @@ class Participant {
/// if participant is currently speaking /// if participant is currently speaking
bool get isSpeaking => _isSpeaking; bool get isSpeaking => _isSpeaking;
/// true if participant is publishing an audio track and is muted
bool get isMuted {
if (audioTracks.values.isEmpty) {
return false;
}
return audioTracks.values.first.muted;
}
bool get hasAudio => audioTracks.length > 0;
bool get hasVideo => videoTracks.length > 0;
/// tracks that are subscribed to
List<TrackPublication> get subscribedTracks {
List<TrackPublication> result = [];
for (var track in tracks.values) {
if (track.subscribed) {
result.add(track);
}
}
return result;
}
/// internal use
bool get hasInfo => _participantInfo != null; bool get hasInfo => _participantInfo != null;
Participant(this.sid, this.identity); Participant(this.sid, this.identity);
@@ -76,6 +112,7 @@ class Participant {
} }
delegate?.onSpeakingChanged(this, speaking); delegate?.onSpeakingChanged(this, speaking);
roomDelegate?.onSpeakingChanged(this, speaking); roomDelegate?.onSpeakingChanged(this, speaking);
notifyListeners();
} }
_setMetadata(String md) { _setMetadata(String md) {
@@ -84,6 +121,7 @@ class Participant {
if (changed) { if (changed) {
delegate?.onMetadataChanged(this); delegate?.onMetadataChanged(this);
roomDelegate?.onMetadataChanged(this); roomDelegate?.onMetadataChanged(this);
notifyListeners();
} }
} }
@@ -96,6 +134,10 @@ class Participant {
this._participantInfo = info; this._participantInfo = info;
} }
muteChanged() {
notifyListeners();
}
addTrackPublication(TrackPublication pub) { addTrackPublication(TrackPublication pub) {
pub.track?.sid = pub.sid; pub.track?.sid = pub.sid;
tracks[pub.sid] = pub; tracks[pub.sid] = pub;
+2 -1
View File
@@ -63,6 +63,7 @@ class RemoteParticipant extends Participant {
delegate?.onTrackSubscribed(this, track, pub); delegate?.onTrackSubscribed(this, track, pub);
roomDelegate?.onTrackSubscribed(this, track, pub); roomDelegate?.onTrackSubscribed(this, track, pub);
notifyListeners();
} }
@override @override
@@ -95,7 +96,6 @@ class RemoteParticipant extends Participant {
delegate?.onTrackPublished(this, pub); delegate?.onTrackPublished(this, pub);
roomDelegate?.onTrackPublished(this, pub); roomDelegate?.onTrackPublished(this, pub);
} }
return;
} }
// remove tracks // remove tracks
@@ -120,6 +120,7 @@ class RemoteParticipant extends Participant {
track.stop(); track.stop();
delegate?.onTrackUnsubscribed(this, track, pub); delegate?.onTrackUnsubscribed(this, track, pub);
roomDelegate?.onTrackUnsubscribed(this, track, pub); roomDelegate?.onTrackUnsubscribed(this, track, pub);
notifyListeners();
} }
if (sendUnpublish) { if (sendUnpublish) {
delegate?.onTrackUnpublished(this, pub); delegate?.onTrackUnpublished(this, pub);
+1 -1
View File
@@ -1,7 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'dart:collection'; import 'dart:collection';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart'; import 'package:flutter_webrtc/flutter_webrtc.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
@@ -10,4 +10,22 @@ class LocalTrackPublication extends TrackPublication {
: super.fromInfo(info) { : super.fromInfo(info) {
this.track = track; this.track = track;
} }
set muted(bool val) {
if (val == muted) {
return;
}
super.muted = val;
track?.mediaTrack.enabled = !val;
_participant.engine.client.sendMuteTrack(sid, val);
if (val) {
_participant.delegate?.onTrackMuted(_participant, this);
_participant.roomDelegate?.onTrackMuted(_participant, this);
} else {
_participant.delegate?.onTrackUnmuted(_participant, this);
_participant.roomDelegate?.onTrackUnmuted(_participant, this);
}
_participant.muteChanged();
}
} }
@@ -46,6 +46,7 @@ class RemoteTrackPublication extends TrackPublication {
_participant.delegate?.onTrackUnmuted(_participant, this); _participant.delegate?.onTrackUnmuted(_participant, this);
_participant.roomDelegate?.onTrackUnmuted(_participant, this); _participant.roomDelegate?.onTrackUnmuted(_participant, this);
} }
_participant.muteChanged();
} }
RemoteTrackPublication(TrackInfo info, this._participant, [Track? track]) RemoteTrackPublication(TrackInfo info, this._participant, [Track? track])