From 60032580893dc45a2b18b2426eafdfbe8c159cb3 Mon Sep 17 00:00:00 2001 From: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> Date: Thu, 9 Dec 2021 13:22:03 +0700 Subject: [PATCH] more docs --- lib/src/events.dart | 25 ++++++++++++- lib/src/livekit.dart | 4 +- lib/src/participant/local_participant.dart | 10 ++++- lib/src/participant/participant.dart | 43 ++++++++++++---------- lib/src/rtc_engine.dart | 10 +++-- 5 files changed, 66 insertions(+), 26 deletions(-) diff --git a/lib/src/events.dart b/lib/src/events.dart index a5cebfe..f31ea68 100644 --- a/lib/src/events.dart +++ b/lib/src/events.dart @@ -1,4 +1,5 @@ import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; +import 'package:meta/meta.dart'; import 'participant/local_participant.dart'; import 'participant/participant.dart'; @@ -10,17 +11,26 @@ import 'publication/remote_track_publication.dart'; import 'publication/track_publication.dart'; import 'track/track.dart'; import 'types.dart'; +import 'room.dart'; +import 'rtc_engine.dart'; +import 'signal_client.dart'; +/// Base type for all LiveKit events. abstract class LiveKitEvent {} +/// Base type for all [Room] events. abstract class RoomEvent implements LiveKitEvent {} +/// Base type for all [Participant] events. abstract class ParticipantEvent implements LiveKitEvent {} +/// Base type for all [Track] events. abstract class TrackEvent implements LiveKitEvent {} +/// Base type for all [RTCEngine] events. abstract class EngineEvent implements LiveKitEvent {} +/// Base type for all [SignalClient] events. abstract class SignalEvent implements LiveKitEvent {} /// When the connection to the server has been interrupted and it's attempting @@ -277,6 +287,8 @@ class EngineRemoteMuteChangedEvent with EngineEvent { // // Signal events // + +@internal class SignalConnectedEvent with SignalEvent { final lk_rtc.JoinResponse response; const SignalConnectedEvent({ @@ -284,6 +296,7 @@ class SignalConnectedEvent with SignalEvent { }); } +@internal class SignalCloseEvent with SignalEvent { final CloseReason? reason; const SignalCloseEvent({ @@ -291,6 +304,7 @@ class SignalCloseEvent with SignalEvent { }); } +@internal class SignalOfferEvent with SignalEvent { final rtc.RTCSessionDescription sd; const SignalOfferEvent({ @@ -298,6 +312,7 @@ class SignalOfferEvent with SignalEvent { }); } +@internal class SignalAnswerEvent with SignalEvent { final rtc.RTCSessionDescription sd; const SignalAnswerEvent({ @@ -305,6 +320,7 @@ class SignalAnswerEvent with SignalEvent { }); } +@internal class SignalTrickleEvent with SignalEvent { final rtc.RTCIceCandidate candidate; final lk_rtc.SignalTarget target; @@ -314,6 +330,7 @@ class SignalTrickleEvent with SignalEvent { }); } +@internal // relayed by Engine class SignalParticipantUpdateEvent with SignalEvent, EngineEvent { final List participants; @@ -322,6 +339,7 @@ class SignalParticipantUpdateEvent with SignalEvent, EngineEvent { }); } +@internal class SignalConnectionQualityUpdateEvent with SignalEvent, EngineEvent { final List updates; const SignalConnectionQualityUpdateEvent({ @@ -329,6 +347,7 @@ class SignalConnectionQualityUpdateEvent with SignalEvent, EngineEvent { }); } +@internal class SignalLocalTrackPublishedEvent with SignalEvent { final String cid; 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 class SignalSpeakersChangedEvent with SignalEvent, EngineEvent { final List speakers; @@ -347,6 +367,7 @@ class SignalSpeakersChangedEvent with SignalEvent, EngineEvent { }); } +@internal // Event received through data channel class EngineActiveSpeakersUpdateEvent with EngineEvent { final List speakers; @@ -355,6 +376,7 @@ class EngineActiveSpeakersUpdateEvent with EngineEvent { }); } +@internal class SignalLeaveEvent with SignalEvent { final bool canReconnect; const SignalLeaveEvent({ @@ -362,6 +384,7 @@ class SignalLeaveEvent with SignalEvent { }); } +@internal class SignalMuteTrackEvent with SignalEvent { final String sid; final bool muted; diff --git a/lib/src/livekit.dart b/lib/src/livekit.dart index af63094..cfa6a27 100644 --- a/lib/src/livekit.dart +++ b/lib/src/livekit.dart @@ -6,7 +6,9 @@ import 'room.dart'; class LiveKitClient { 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 connect( String url, String token, { diff --git a/lib/src/participant/local_participant.dart b/lib/src/participant/local_participant.dart index 763b8ca..13a9e86 100644 --- a/lib/src/participant/local_participant.dart +++ b/lib/src/participant/local_participant.dart @@ -12,13 +12,16 @@ import '../options.dart'; import '../proto/livekit_models.pb.dart' as lk_models; import '../publication/local_track_publication.dart'; import '../rtc_engine.dart'; +import '../track/local.dart'; import '../track/local/audio.dart'; import '../track/local/video.dart'; import '../types.dart'; import '../utils.dart'; +import '../room.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 { @internal final VideoPublishOptions? defaultVideoPublishOptions; @@ -40,7 +43,8 @@ class LocalParticipant extends Participant { 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> publishAudioTrack( LocalAudioTrack track, { AudioPublishOptions? options, @@ -250,12 +254,14 @@ class LocalParticipant extends Participant { List get subscribedTracks => super.subscribedTracks.cast().toList(); + /// A convenience property to get all video tracks. @override List> get videoTracks => trackPublications.values .whereType>() .toList(); + /// A convenience property to get all audio tracks. @override List> get audioTracks => trackPublications.values diff --git a/lib/src/participant/participant.dart b/lib/src/participant/participant.dart index 666f817..08c7017 100644 --- a/lib/src/participant/participant.dart +++ b/lib/src/participant/participant.dart @@ -29,30 +29,31 @@ abstract class Participant @internal final RTCEngine engine; - /// map of track sid => published track + /// Map of track sid => published track final Map trackPublications = {}; - /// audio level between 0-1, 1 being the loudest + /// Audio level between 0-1, 1 being the loudest. double audioLevel = 0; - /// server assigned unique id + /// Server assigned unique id. final String sid; - /// user-assigned identity + /// User-assigned identity. String identity; - /// client-assigned metadata, opaque to livekit + /// Client-assigned metadata, opaque to livekit. String? metadata; - /// when the participant had last spoken + /// When the participant had last spoken. DateTime? lastSpokeAt; lk_models.ParticipantInfo? _participantInfo; bool _isSpeaking = false; + /// Connection quality between the [Participant] and the server. ConnectionQuality _connectionQuality = ConnectionQuality.unknown; - // suppport for multiple event listeners + // Suppport for multiple event listeners. final EventsEmitter roomEvents; /// when the participant joined the room @@ -169,9 +170,10 @@ abstract class Participant trackPublications[pub.sid] = pub; } - // Must implement + // Must be implemented by subclasses. Future unpublishTrack(String trackSid, {bool notify = true}); + /// Convenience method to unpublish all tracks. Future unpublishAllTracks({bool notify = true}) async { final trackSids = trackPublications.keys.toSet(); for (final trackid in trackSids) { @@ -179,31 +181,26 @@ abstract class Participant } } - // - // 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; - + /// Convenience property to check whether [TrackSource.camera] is published or not. bool isCameraEnabled() { return !(getTrackPublicationBySource(TrackSource.camera)?.muted ?? true); } + /// Convenience property to check whether [TrackSource.microphone] is published or not. bool isMicrophoneEnabled() { return !(getTrackPublicationBySource(TrackSource.microphone)?.muted ?? true); } + /// Convenience property to check whether [TrackSource.screenShareVideo] is published or not. bool isScreenShareEnabled() { return !(getTrackPublicationBySource(TrackSource.screenShareVideo)?.muted ?? 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) { if (source == TrackSource.unknown) return null; // try to find by source @@ -226,4 +223,12 @@ abstract class Participant e.kind == lk_models.TrackType.AUDIO && 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; } diff --git a/lib/src/rtc_engine.dart b/lib/src/rtc_engine.dart index 0ccdf60..e09e0ae 100644 --- a/lib/src/rtc_engine.dart +++ b/lib/src/rtc_engine.dart @@ -21,6 +21,7 @@ import 'signal_client.dart'; import 'support/disposable.dart'; import 'transport.dart'; import 'types.dart'; +import 'room.dart'; class RTCEngine extends Disposable with EventsEmittable { static const _lossyDCLabel = '_lossy'; @@ -49,7 +50,7 @@ class RTCEngine extends Disposable with EventsEmittable { ConnectionState _connectionState = ConnectionState.disconnected; - /// connection state of the room + /// Connection state of the [Room]. ConnectionState get connectionState => _connectionState; // true if publisher connection has already been established. @@ -120,7 +121,7 @@ class RTCEngine extends Disposable with EventsEmittable { return event.response; } - // there is no side-effect calling this method multiple times + /// Close connection between the server. Future close() async { logger.fine('[$objectId] close()'); if (_connectionState == ConnectionState.disconnected) { @@ -143,6 +144,7 @@ class RTCEngine extends Disposable with EventsEmittable { // notifyListeners(); } + @internal Future addTrack({ required String cid, required String name, @@ -173,6 +175,7 @@ class RTCEngine extends Disposable with EventsEmittable { return event.track; } + @internal Future negotiate({bool? iceRestart}) async { if (publisher == null) { return; @@ -182,7 +185,7 @@ class RTCEngine extends Disposable with EventsEmittable { publisher!.negotiate(null); } - /* @internal */ + @internal Future sendDataPacket( lk_models.DataPacket packet, ) async { @@ -227,6 +230,7 @@ class RTCEngine extends Disposable with EventsEmittable { logger.fine('[PUBLISHER] connected'); } + @internal Future reconnect() async { if (_connectionState == ConnectionState.disconnected) { logger.fine('$objectId reconnect() already closed');