more docs

This commit is contained in:
Hiroshi Horie
2021-12-09 13:22:03 +07:00
parent b6b48ea310
commit 6003258089
5 changed files with 66 additions and 26 deletions
+24 -1
View File
@@ -1,4 +1,5 @@
import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc;
import 'package:meta/meta.dart';
import 'participant/local_participant.dart'; import 'participant/local_participant.dart';
import 'participant/participant.dart'; import 'participant/participant.dart';
@@ -10,17 +11,26 @@ import 'publication/remote_track_publication.dart';
import 'publication/track_publication.dart'; import 'publication/track_publication.dart';
import 'track/track.dart'; import 'track/track.dart';
import 'types.dart'; import 'types.dart';
import 'room.dart';
import 'rtc_engine.dart';
import 'signal_client.dart';
/// Base type for all LiveKit events.
abstract class LiveKitEvent {} abstract class LiveKitEvent {}
/// Base type for all [Room] events.
abstract class RoomEvent implements LiveKitEvent {} abstract class RoomEvent implements LiveKitEvent {}
/// Base type for all [Participant] events.
abstract class ParticipantEvent implements LiveKitEvent {} abstract class ParticipantEvent implements LiveKitEvent {}
/// Base type for all [Track] events.
abstract class TrackEvent implements LiveKitEvent {} abstract class TrackEvent implements LiveKitEvent {}
/// Base type for all [RTCEngine] events.
abstract class EngineEvent implements LiveKitEvent {} abstract class EngineEvent implements LiveKitEvent {}
/// Base type for all [SignalClient] events.
abstract class SignalEvent implements LiveKitEvent {} abstract class SignalEvent implements LiveKitEvent {}
/// When the connection to the server has been interrupted and it's attempting /// When the connection to the server has been interrupted and it's attempting
@@ -277,6 +287,8 @@ class EngineRemoteMuteChangedEvent with EngineEvent {
// //
// Signal events // Signal events
// //
@internal
class SignalConnectedEvent with SignalEvent { class SignalConnectedEvent with SignalEvent {
final lk_rtc.JoinResponse response; final lk_rtc.JoinResponse response;
const SignalConnectedEvent({ const SignalConnectedEvent({
@@ -284,6 +296,7 @@ class SignalConnectedEvent with SignalEvent {
}); });
} }
@internal
class SignalCloseEvent with SignalEvent { class SignalCloseEvent with SignalEvent {
final CloseReason? reason; final CloseReason? reason;
const SignalCloseEvent({ const SignalCloseEvent({
@@ -291,6 +304,7 @@ class SignalCloseEvent with SignalEvent {
}); });
} }
@internal
class SignalOfferEvent with SignalEvent { class SignalOfferEvent with SignalEvent {
final rtc.RTCSessionDescription sd; final rtc.RTCSessionDescription sd;
const SignalOfferEvent({ const SignalOfferEvent({
@@ -298,6 +312,7 @@ class SignalOfferEvent with SignalEvent {
}); });
} }
@internal
class SignalAnswerEvent with SignalEvent { class SignalAnswerEvent with SignalEvent {
final rtc.RTCSessionDescription sd; final rtc.RTCSessionDescription sd;
const SignalAnswerEvent({ const SignalAnswerEvent({
@@ -305,6 +320,7 @@ class SignalAnswerEvent with SignalEvent {
}); });
} }
@internal
class SignalTrickleEvent with SignalEvent { class SignalTrickleEvent with SignalEvent {
final rtc.RTCIceCandidate candidate; final rtc.RTCIceCandidate candidate;
final lk_rtc.SignalTarget target; final lk_rtc.SignalTarget target;
@@ -314,6 +330,7 @@ class SignalTrickleEvent with SignalEvent {
}); });
} }
@internal
// relayed by Engine // relayed by Engine
class SignalParticipantUpdateEvent with SignalEvent, EngineEvent { class SignalParticipantUpdateEvent with SignalEvent, EngineEvent {
final List<lk_models.ParticipantInfo> participants; final List<lk_models.ParticipantInfo> participants;
@@ -322,6 +339,7 @@ class SignalParticipantUpdateEvent with SignalEvent, EngineEvent {
}); });
} }
@internal
class SignalConnectionQualityUpdateEvent with SignalEvent, EngineEvent { class SignalConnectionQualityUpdateEvent with SignalEvent, EngineEvent {
final List<lk_rtc.ConnectionQualityInfo> updates; final List<lk_rtc.ConnectionQualityInfo> updates;
const SignalConnectionQualityUpdateEvent({ const SignalConnectionQualityUpdateEvent({
@@ -329,6 +347,7 @@ class SignalConnectionQualityUpdateEvent with SignalEvent, EngineEvent {
}); });
} }
@internal
class SignalLocalTrackPublishedEvent with SignalEvent { class SignalLocalTrackPublishedEvent with SignalEvent {
final String cid; final String cid;
final lk_models.TrackInfo track; final lk_models.TrackInfo track;
@@ -338,7 +357,8 @@ class SignalLocalTrackPublishedEvent with SignalEvent {
}); });
} }
// speaker update received through websocket @internal
// Speaker update received through websocket
// relayed by Engine // relayed by Engine
class SignalSpeakersChangedEvent with SignalEvent, EngineEvent { class SignalSpeakersChangedEvent with SignalEvent, EngineEvent {
final List<lk_models.SpeakerInfo> speakers; final List<lk_models.SpeakerInfo> speakers;
@@ -347,6 +367,7 @@ class SignalSpeakersChangedEvent with SignalEvent, EngineEvent {
}); });
} }
@internal
// Event received through data channel // Event received through data channel
class EngineActiveSpeakersUpdateEvent with EngineEvent { class EngineActiveSpeakersUpdateEvent with EngineEvent {
final List<lk_models.SpeakerInfo> speakers; final List<lk_models.SpeakerInfo> speakers;
@@ -355,6 +376,7 @@ class EngineActiveSpeakersUpdateEvent with EngineEvent {
}); });
} }
@internal
class SignalLeaveEvent with SignalEvent { class SignalLeaveEvent with SignalEvent {
final bool canReconnect; final bool canReconnect;
const SignalLeaveEvent({ const SignalLeaveEvent({
@@ -362,6 +384,7 @@ class SignalLeaveEvent with SignalEvent {
}); });
} }
@internal
class SignalMuteTrackEvent with SignalEvent { class SignalMuteTrackEvent with SignalEvent {
final String sid; final String sid;
final bool muted; final bool muted;
+3 -1
View File
@@ -6,7 +6,9 @@ import 'room.dart';
class LiveKitClient { class LiveKitClient {
static const version = '0.5.4'; static const version = '0.5.4';
/// Connects to a LiveKit room /// Convenience method for connecting to a LiveKit server.
/// Returns a [Room] upon a successful connect or throws when it fails.
/// Alternatively, it is possible to instantiate [Room] and call [Room.connect] directly.
static Future<Room> connect( static Future<Room> connect(
String url, String url,
String token, { String token, {
+8 -2
View File
@@ -12,13 +12,16 @@ import '../options.dart';
import '../proto/livekit_models.pb.dart' as lk_models; import '../proto/livekit_models.pb.dart' as lk_models;
import '../publication/local_track_publication.dart'; import '../publication/local_track_publication.dart';
import '../rtc_engine.dart'; import '../rtc_engine.dart';
import '../track/local.dart';
import '../track/local/audio.dart'; import '../track/local/audio.dart';
import '../track/local/video.dart'; import '../track/local/video.dart';
import '../types.dart'; import '../types.dart';
import '../utils.dart'; import '../utils.dart';
import '../room.dart';
import 'participant.dart'; import 'participant.dart';
/// Represents the current participant in the room. /// Represents the current participant in the room. Instance of [LocalParticipant] is automatically
/// created after successfully connecting to a [Room] and will be accessible from [Room.localParticipant].
class LocalParticipant extends Participant<LocalTrackPublication> { class LocalParticipant extends Participant<LocalTrackPublication> {
@internal @internal
final VideoPublishOptions? defaultVideoPublishOptions; final VideoPublishOptions? defaultVideoPublishOptions;
@@ -40,7 +43,8 @@ class LocalParticipant extends Participant<LocalTrackPublication> {
updateFromInfo(info); updateFromInfo(info);
} }
/// publish an audio track to the room /// Publish an [AudioTrack] to the [Room].
/// For most cases, using [setMicrophoneEnabled] would be simpler and recommended.
Future<LocalTrackPublication<LocalAudioTrack>> publishAudioTrack( Future<LocalTrackPublication<LocalAudioTrack>> publishAudioTrack(
LocalAudioTrack track, { LocalAudioTrack track, {
AudioPublishOptions? options, AudioPublishOptions? options,
@@ -250,12 +254,14 @@ class LocalParticipant extends Participant<LocalTrackPublication> {
List<LocalTrackPublication> get subscribedTracks => List<LocalTrackPublication> get subscribedTracks =>
super.subscribedTracks.cast<LocalTrackPublication>().toList(); super.subscribedTracks.cast<LocalTrackPublication>().toList();
/// A convenience property to get all video tracks.
@override @override
List<LocalTrackPublication<LocalVideoTrack>> get videoTracks => List<LocalTrackPublication<LocalVideoTrack>> get videoTracks =>
trackPublications.values trackPublications.values
.whereType<LocalTrackPublication<LocalVideoTrack>>() .whereType<LocalTrackPublication<LocalVideoTrack>>()
.toList(); .toList();
/// A convenience property to get all audio tracks.
@override @override
List<LocalTrackPublication<LocalAudioTrack>> get audioTracks => List<LocalTrackPublication<LocalAudioTrack>> get audioTracks =>
trackPublications.values trackPublications.values
+24 -19
View File
@@ -29,30 +29,31 @@ abstract class Participant<T extends TrackPublication>
@internal @internal
final RTCEngine engine; final RTCEngine engine;
/// map of track sid => published track /// Map of track sid => published track
final Map<String, T> trackPublications = {}; final Map<String, T> trackPublications = {};
/// audio level between 0-1, 1 being the loudest /// Audio level between 0-1, 1 being the loudest.
double audioLevel = 0; double audioLevel = 0;
/// server assigned unique id /// Server assigned unique id.
final String sid; final String sid;
/// user-assigned identity /// User-assigned identity.
String identity; String identity;
/// client-assigned metadata, opaque to livekit /// Client-assigned metadata, opaque to livekit.
String? metadata; String? metadata;
/// when the participant had last spoken /// When the participant had last spoken.
DateTime? lastSpokeAt; DateTime? lastSpokeAt;
lk_models.ParticipantInfo? _participantInfo; lk_models.ParticipantInfo? _participantInfo;
bool _isSpeaking = false; bool _isSpeaking = false;
/// Connection quality between the [Participant] and the server.
ConnectionQuality _connectionQuality = ConnectionQuality.unknown; ConnectionQuality _connectionQuality = ConnectionQuality.unknown;
// suppport for multiple event listeners // Suppport for multiple event listeners.
final EventsEmitter<RoomEvent> roomEvents; final EventsEmitter<RoomEvent> roomEvents;
/// when the participant joined the room /// when the participant joined the room
@@ -169,9 +170,10 @@ abstract class Participant<T extends TrackPublication>
trackPublications[pub.sid] = pub; trackPublications[pub.sid] = pub;
} }
// Must implement // Must be implemented by subclasses.
Future<void> unpublishTrack(String trackSid, {bool notify = true}); Future<void> unpublishTrack(String trackSid, {bool notify = true});
/// Convenience method to unpublish all tracks.
Future<void> unpublishAllTracks({bool notify = true}) async { Future<void> unpublishAllTracks({bool notify = true}) async {
final trackSids = trackPublications.keys.toSet(); final trackSids = trackPublications.keys.toSet();
for (final trackid in trackSids) { for (final trackid in trackSids) {
@@ -179,31 +181,26 @@ abstract class Participant<T extends TrackPublication>
} }
} }
// /// Convenience property to check whether [TrackSource.camera] is published or not.
// Equality operators
// Object is considered equal when sid is equal
//
@override
int get hashCode => sid.hashCode;
@override
bool operator ==(Object other) => other is Participant && sid == other.sid;
bool isCameraEnabled() { bool isCameraEnabled() {
return !(getTrackPublicationBySource(TrackSource.camera)?.muted ?? true); return !(getTrackPublicationBySource(TrackSource.camera)?.muted ?? true);
} }
/// Convenience property to check whether [TrackSource.microphone] is published or not.
bool isMicrophoneEnabled() { bool isMicrophoneEnabled() {
return !(getTrackPublicationBySource(TrackSource.microphone)?.muted ?? return !(getTrackPublicationBySource(TrackSource.microphone)?.muted ??
true); true);
} }
/// Convenience property to check whether [TrackSource.screenShareVideo] is published or not.
bool isScreenShareEnabled() { bool isScreenShareEnabled() {
return !(getTrackPublicationBySource(TrackSource.screenShareVideo)?.muted ?? return !(getTrackPublicationBySource(TrackSource.screenShareVideo)?.muted ??
true); true);
} }
/// Find a track publication by its [TrackSource] /// Tries to find a [TrackPublication] by its [TrackSource]. Otherwise, will
/// return a compatible type of [TrackPublication] for the [TrackSource] specified.
/// returns null when not found.
T? getTrackPublicationBySource(TrackSource source) { T? getTrackPublicationBySource(TrackSource source) {
if (source == TrackSource.unknown) return null; if (source == TrackSource.unknown) return null;
// try to find by source // try to find by source
@@ -226,4 +223,12 @@ abstract class Participant<T extends TrackPublication>
e.kind == lk_models.TrackType.AUDIO && e.kind == lk_models.TrackType.AUDIO &&
e.name == Track.screenShareName)); e.name == Track.screenShareName));
} }
// Equality operators
// Object is considered equal when sid is equal
@override
int get hashCode => sid.hashCode;
@override
bool operator ==(Object other) => other is Participant && sid == other.sid;
} }
+7 -3
View File
@@ -21,6 +21,7 @@ import 'signal_client.dart';
import 'support/disposable.dart'; import 'support/disposable.dart';
import 'transport.dart'; import 'transport.dart';
import 'types.dart'; import 'types.dart';
import 'room.dart';
class RTCEngine extends Disposable with EventsEmittable<EngineEvent> { class RTCEngine extends Disposable with EventsEmittable<EngineEvent> {
static const _lossyDCLabel = '_lossy'; static const _lossyDCLabel = '_lossy';
@@ -49,7 +50,7 @@ class RTCEngine extends Disposable with EventsEmittable<EngineEvent> {
ConnectionState _connectionState = ConnectionState.disconnected; ConnectionState _connectionState = ConnectionState.disconnected;
/// connection state of the room /// Connection state of the [Room].
ConnectionState get connectionState => _connectionState; ConnectionState get connectionState => _connectionState;
// true if publisher connection has already been established. // true if publisher connection has already been established.
@@ -120,7 +121,7 @@ class RTCEngine extends Disposable with EventsEmittable<EngineEvent> {
return event.response; return event.response;
} }
// there is no side-effect calling this method multiple times /// Close connection between the server.
Future<void> close() async { Future<void> close() async {
logger.fine('[$objectId] close()'); logger.fine('[$objectId] close()');
if (_connectionState == ConnectionState.disconnected) { if (_connectionState == ConnectionState.disconnected) {
@@ -143,6 +144,7 @@ class RTCEngine extends Disposable with EventsEmittable<EngineEvent> {
// notifyListeners(); // notifyListeners();
} }
@internal
Future<lk_models.TrackInfo> addTrack({ Future<lk_models.TrackInfo> addTrack({
required String cid, required String cid,
required String name, required String name,
@@ -173,6 +175,7 @@ class RTCEngine extends Disposable with EventsEmittable<EngineEvent> {
return event.track; return event.track;
} }
@internal
Future<void> negotiate({bool? iceRestart}) async { Future<void> negotiate({bool? iceRestart}) async {
if (publisher == null) { if (publisher == null) {
return; return;
@@ -182,7 +185,7 @@ class RTCEngine extends Disposable with EventsEmittable<EngineEvent> {
publisher!.negotiate(null); publisher!.negotiate(null);
} }
/* @internal */ @internal
Future<void> sendDataPacket( Future<void> sendDataPacket(
lk_models.DataPacket packet, lk_models.DataPacket packet,
) async { ) async {
@@ -227,6 +230,7 @@ class RTCEngine extends Disposable with EventsEmittable<EngineEvent> {
logger.fine('[PUBLISHER] connected'); logger.fine('[PUBLISHER] connected');
} }
@internal
Future<void> reconnect() async { Future<void> reconnect() async {
if (_connectionState == ConnectionState.disconnected) { if (_connectionState == ConnectionState.disconnected) {
logger.fine('$objectId reconnect() already closed'); logger.fine('$objectId reconnect() already closed');