diff --git a/example/lib/pages/connect.dart b/example/lib/pages/connect.dart index e5857a1..15a75d4 100644 --- a/example/lib/pages/connect.dart +++ b/example/lib/pages/connect.dart @@ -78,7 +78,7 @@ class _ConnectPageState extends State { final room = await LiveKitClient.connect( _uriCtrl.text, _tokenCtrl.text, - options: ConnectOptions( + roomOptions: RoomOptions( defaultVideoPublishOptions: VideoPublishOptions( simulcast: _simulcast, ), diff --git a/lib/src/extensions.dart b/lib/src/extensions.dart index a285ff3..8dba2ae 100644 --- a/lib/src/extensions.dart +++ b/lib/src/extensions.dart @@ -38,10 +38,10 @@ extension ObjectExt on Object { extension ProtocolVersionExt on ProtocolVersion { String toStringValue() => { - ProtocolVersion.protocol2: '2', - ProtocolVersion.protocol3: '3', - ProtocolVersion.protocol4: '4', - ProtocolVersion.protocol5: '5', + ProtocolVersion.v2: '2', + ProtocolVersion.v3: '3', + ProtocolVersion.v4: '4', + ProtocolVersion.v5: '5', }[this]!; } diff --git a/lib/src/livekit.dart b/lib/src/livekit.dart index cfa6a27..3f12fc5 100644 --- a/lib/src/livekit.dart +++ b/lib/src/livekit.dart @@ -12,14 +12,16 @@ class LiveKitClient { static Future connect( String url, String token, { - ConnectOptions? options, + ConnectOptions? connectOptions, + RoomOptions? roomOptions, }) async { final room = Room(); try { await room.connect( url, token, - options: options, + connectOptions: connectOptions, + roomOptions: roomOptions, ); return room; } catch (error) { diff --git a/lib/src/options.dart b/lib/src/options.dart index a842eb1..4f3d2ad 100644 --- a/lib/src/options.dart +++ b/lib/src/options.dart @@ -1,12 +1,23 @@ +import 'package:livekit_client/src/types.dart'; import 'track/options.dart'; import 'track/track.dart'; -/// Options when joining a room. -/// {@category Room} class ConnectOptions { /// Auto-subscribe to room tracks upon connect, defaults to true. final bool autoSubscribe; + final RTCConfiguration rtcConfiguration; + final ProtocolVersion protocolVersion; + const ConnectOptions({ + this.autoSubscribe = true, + this.rtcConfiguration = const RTCConfiguration(), + this.protocolVersion = ProtocolVersion.v5, + }); +} + +/// Options when joining a room. +/// {@category Room} +class RoomOptions { /// Default options used when publishing a video track final VideoPublishOptions defaultVideoPublishOptions; @@ -26,8 +37,7 @@ class ConnectOptions { /// defaults to true. final bool stopLocalTrackOnUnpublish; - const ConnectOptions({ - this.autoSubscribe = true, + const RoomOptions({ this.defaultVideoPublishOptions = const VideoPublishOptions(), this.defaultAudioPublishOptions = const AudioPublishOptions(), this.optimizeVideo = true, diff --git a/lib/src/participant/local_participant.dart b/lib/src/participant/local_participant.dart index 040f639..fb4d410 100644 --- a/lib/src/participant/local_participant.dart +++ b/lib/src/participant/local_participant.dart @@ -7,12 +7,10 @@ import '../events.dart'; import '../exceptions.dart'; import '../extensions.dart'; import '../logger.dart'; -import '../managers/event.dart'; import '../options.dart'; import '../proto/livekit_models.pb.dart' as lk_models; import '../publication/local_track_publication.dart'; import '../room.dart'; -import '../rtc_engine.dart'; import '../track/local.dart'; import '../track/local/audio.dart'; import '../track/local/video.dart'; @@ -23,22 +21,14 @@ import 'participant.dart'; /// 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; - @internal - final AudioPublishOptions? defaultAudioPublishOptions; - + // LocalParticipant({ - required RTCEngine engine, + required Room room, required lk_models.ParticipantInfo info, - this.defaultVideoPublishOptions, - this.defaultAudioPublishOptions, - required EventsEmitter roomEvents, }) : super( - engine: engine, + room: room, sid: info.sid, identity: info.identity, - roomEvents: roomEvents, ) { updateFromInfo(info); } @@ -47,7 +37,7 @@ class LocalParticipant extends Participant { /// For most cases, using [setMicrophoneEnabled] would be simpler and recommended. Future> publishAudioTrack( LocalAudioTrack track, { - AudioPublishOptions? options, + AudioPublishOptions? publishOptions, }) async { if (audioTracks.any( (e) => e.track?.mediaStreamTrack.id == track.mediaStreamTrack.id)) { @@ -55,14 +45,15 @@ class LocalParticipant extends Participant { } // Use defaultPublishOptions if options is null - options = options ?? defaultAudioPublishOptions; + publishOptions = + publishOptions ?? room.roomOptions?.defaultAudioPublishOptions; - final trackInfo = await engine.addTrack( + final trackInfo = await room.engine.addTrack( cid: track.getCid(), name: track.name, kind: track.kind, source: track.source.toPBType(), - dtx: options?.dtx, + dtx: publishOptions?.dtx, ); await track.start(); @@ -71,12 +62,13 @@ class LocalParticipant extends Participant { direction: rtc.TransceiverDirection.SendOnly, ); // addTransceiver cannot pass in a kind parameter due to a bug in flutter-webrtc (web) - track.transceiver = await engine.publisher?.pc.addTransceiver( + track.transceiver = await room.engine.publisher?.pc.addTransceiver( track: track.mediaStreamTrack, kind: rtc.RTCRtpMediaType.RTCRtpMediaTypeAudio, init: transceiverInit, ); - await engine.negotiate(); + + await room.engine.negotiate(); final pub = LocalTrackPublication( participant: this, @@ -85,7 +77,7 @@ class LocalParticipant extends Participant { ); addTrackPublication(pub); - [events, roomEvents].emit(LocalTrackPublishedEvent( + [events, room.events].emit(LocalTrackPublishedEvent( participant: this, publication: pub, )); @@ -96,7 +88,7 @@ class LocalParticipant extends Participant { /// Publish a video track to the room Future> publishVideoTrack( LocalVideoTrack track, { - VideoPublishOptions? options, + VideoPublishOptions? publishOptions, }) async { if (videoTracks.any( (e) => e.track?.mediaStreamTrack.id == track.mediaStreamTrack.id)) { @@ -104,7 +96,8 @@ class LocalParticipant extends Participant { } // Use defaultPublishOptions if options is null - options = options ?? defaultVideoPublishOptions; + publishOptions = + publishOptions ?? room.roomOptions?.defaultVideoPublishOptions; // use constraints passed to getUserMedia by default int width = track.currentOptions.params.width; @@ -126,7 +119,7 @@ class LocalParticipant extends Participant { } } - final trackInfo = await engine.addTrack( + final trackInfo = await room.engine.addTrack( cid: track.getCid(), name: track.name, kind: track.kind, @@ -139,13 +132,13 @@ class LocalParticipant extends Participant { await track.start(); logger.fine( - 'Compute encodings with resolution: ${width}x${height}, options: ${options}'); + 'Compute encodings with resolution: ${width}x${height}, options: ${publishOptions}'); // Video encodings and simulcasts final encodings = Utils.computeVideoEncodings( width: width, height: height, - options: options, + options: publishOptions, ); logger.fine('Using encodings: ${encodings?.map((e) => e.toMap())}'); @@ -156,14 +149,15 @@ class LocalParticipant extends Participant { streams: [track.mediaStream], ); - logger.fine('publishVideoTrack publisher: ${engine.publisher}'); + logger.fine('publishVideoTrack publisher: ${room.engine.publisher}'); - track.transceiver = await engine.publisher?.pc.addTransceiver( + track.transceiver = await room.engine.publisher?.pc.addTransceiver( track: track.mediaStreamTrack, kind: rtc.RTCRtpMediaType.RTCRtpMediaTypeVideo, init: transceiverInit, ); - await engine.negotiate(); + + await room.engine.negotiate(); final pub = LocalTrackPublication( participant: this, @@ -172,7 +166,7 @@ class LocalParticipant extends Participant { ); addTrackPublication(pub); - [events, roomEvents].emit(LocalTrackPublishedEvent( + [events, room.events].emit(LocalTrackPublishedEvent( participant: this, publication: pub, )); @@ -193,14 +187,15 @@ class LocalParticipant extends Participant { final track = pub.track; if (track != null) { - if (engine.connectOptions.stopLocalTrackOnUnpublish) { + final roomOptions = room.roomOptions ?? const RoomOptions(); + if (roomOptions.stopLocalTrackOnUnpublish) { await track.stop(); } final sender = track.transceiver?.sender; if (sender != null) { try { - await engine.publisher?.pc.removeTrack(sender); + await room.engine.publisher?.pc.removeTrack(sender); } catch (_) { logger.warning('[$objectId] rtc.removeTrack() did throw ${_}'); } @@ -208,13 +203,13 @@ class LocalParticipant extends Participant { // doesn't make sense to negotiate if already disposed if (!isDisposed) { // manual negotiation since track changed - await engine.negotiate(); + await room.engine.negotiate(); } } } if (notify) { - [events, roomEvents].emit(LocalTrackUnpublishedEvent( + [events, room.events].emit(LocalTrackUnpublishedEvent( participant: this, publication: pub, )); @@ -239,7 +234,7 @@ class LocalParticipant extends Participant { ), ); - await engine.sendDataPacket(packet); + await room.engine.sendDataPacket(packet); } /// for internal use diff --git a/lib/src/participant/participant.dart b/lib/src/participant/participant.dart index 08c7017..dd1c8d6 100644 --- a/lib/src/participant/participant.dart +++ b/lib/src/participant/participant.dart @@ -7,7 +7,7 @@ import '../logger.dart'; import '../managers/event.dart'; import '../proto/livekit_models.pb.dart' as lk_models; import '../publication/track_publication.dart'; -import '../rtc_engine.dart'; +import '../room.dart'; import '../support/disposable.dart'; import '../track/track.dart'; import '../types.dart'; @@ -25,9 +25,9 @@ import 'remote_participant.dart'; /// can not be instantiated directly. abstract class Participant extends DisposableChangeNotifier with EventsEmittable { - /// Reference to [RTCEngine] + /// Reference to [Room] @internal - final RTCEngine engine; + final Room room; /// Map of track sid => published track final Map trackPublications = {}; @@ -53,9 +53,6 @@ abstract class Participant /// Connection quality between the [Participant] and the server. ConnectionQuality _connectionQuality = ConnectionQuality.unknown; - // Suppport for multiple event listeners. - final EventsEmitter roomEvents; - /// when the participant joined the room DateTime get joinedAt { final pi = _participantInfo; @@ -95,10 +92,9 @@ abstract class Participant bool get hasInfo => _participantInfo != null; Participant({ - required this.engine, + required this.room, required this.sid, required this.identity, - required this.roomEvents, }) { // Any event emitted will trigger ChangeNotifier events.listen((event) { @@ -134,7 +130,7 @@ abstract class Participant final changed = _participantInfo?.metadata != md; metadata = md; if (changed) { - [events, roomEvents].emit(ParticipantMetadataUpdatedEvent( + [events, room.events].emit(ParticipantMetadataUpdatedEvent( participant: this, )); } @@ -144,7 +140,7 @@ abstract class Participant void updateConnectionQuality(ConnectionQuality quality) { if (_connectionQuality == quality) return; _connectionQuality = quality; - [events, roomEvents].emit(ParticipantConnectionQualityUpdatedEvent( + [events, room.events].emit(ParticipantConnectionQualityUpdatedEvent( participant: this, connectionQuality: _connectionQuality, )); diff --git a/lib/src/participant/remote_participant.dart b/lib/src/participant/remote_participant.dart index 70ad38c..1bfdc78 100644 --- a/lib/src/participant/remote_participant.dart +++ b/lib/src/participant/remote_participant.dart @@ -9,7 +9,6 @@ import '../logger.dart'; import '../managers/event.dart'; import '../proto/livekit_models.pb.dart' as lk_models; import '../publication/remote_track_publication.dart'; -import '../rtc_engine.dart'; import '../track/remote/audio.dart'; import '../track/remote/video.dart'; import '../types.dart'; @@ -34,26 +33,23 @@ class RemoteParticipant extends Participant { .toList(); RemoteParticipant({ - required RTCEngine engine, + required Room room, required String sid, required String identity, - required EventsEmitter roomEvents, }) : super( - engine: engine, + room: room, sid: sid, identity: identity, - roomEvents: roomEvents, ); RemoteParticipant.fromInfo({ - required RTCEngine engine, + required Room room, required lk_models.ParticipantInfo info, required EventsEmitter roomEvents, }) : super( - engine: engine, + room: room, sid: info.sid, identity: info.identity, - roomEvents: roomEvents, ) { updateFromInfo(info); } @@ -118,7 +114,7 @@ class RemoteParticipant extends Participant { await pub.updateTrack(track); addTrackPublication(pub); - [events, roomEvents].emit(TrackSubscribedEvent( + [events, room.events].emit(TrackSubscribedEvent( participant: this, track: track, publication: pub, @@ -167,7 +163,7 @@ class RemoteParticipant extends Participant { participant: this, publication: pub, ); - [events, roomEvents].emit(event); + [events, room.events].emit(event); } } @@ -194,7 +190,7 @@ class RemoteParticipant extends Participant { // if has track if (track != null) { await track.stop(); - [events, roomEvents].emit(TrackUnsubscribedEvent( + [events, room.events].emit(TrackUnsubscribedEvent( participant: this, track: track, publication: pub, @@ -202,7 +198,7 @@ class RemoteParticipant extends Participant { } if (notify) { - [events, roomEvents].emit(TrackUnpublishedEvent( + [events, room.events].emit(TrackUnpublishedEvent( participant: this, publication: pub, )); diff --git a/lib/src/publication/local_track_publication.dart b/lib/src/publication/local_track_publication.dart index 565568c..741dab7 100644 --- a/lib/src/publication/local_track_publication.dart +++ b/lib/src/publication/local_track_publication.dart @@ -33,12 +33,12 @@ class LocalTrackPublication extends TrackPublication { // listen for track muted events ..on((event) { // send signal to server - participant.engine.signalClient.sendMuteTrack(sid, event.muted); + participant.room.engine.signalClient.sendMuteTrack(sid, event.muted); // emit events final newEvent = event.muted ? TrackMutedEvent(participant: participant, track: this) : TrackUnmutedEvent(participant: participant, track: this); - [participant.events, participant.roomEvents].emit(newEvent); + [participant.events, participant.room.events].emit(newEvent); }); // dispose listener when the track is disposed newValue.onDispose(() => listener.dispose()); diff --git a/lib/src/publication/remote_track_publication.dart b/lib/src/publication/remote_track_publication.dart index 589bc42..653aa8f 100644 --- a/lib/src/publication/remote_track_publication.dart +++ b/lib/src/publication/remote_track_publication.dart @@ -4,6 +4,7 @@ import 'dart:ui'; import 'package:collection/collection.dart'; import 'package:meta/meta.dart'; +import 'package:livekit_client/livekit_client.dart'; import '../events.dart'; import '../extensions.dart'; import '../internal/events.dart'; @@ -141,7 +142,7 @@ class RemoteTrackPublication } logger.fine('[Visibility] Sending to server ${settings.toProto3Json()}'); - participant.engine.signalClient.sendUpdateTrackSettings(settings); + participant.room.engine.signalClient.sendUpdateTrackSettings(settings); } @internal @@ -151,9 +152,11 @@ class RemoteTrackPublication // Only listen for visibility updates if video optimization is on // and the attached track is a video track + final roomOptions = participant.room.roomOptions ?? const RoomOptions(); + // if (didUpdate && newValue != null && - participant.engine.connectOptions.optimizeVideo && + roomOptions.optimizeVideo && newValue.kind == lk_models.TrackType.VIDEO) { // // Attach visibility event listener (if video track) @@ -194,7 +197,7 @@ class RemoteTrackPublication // Ideally, we should wait for WebRTC's onRemoveTrack event // but it does not work reliably across platforms. // So for now we will assume remove track succeeded. - [participant.events, participant.roomEvents].emit(TrackUnsubscribedEvent( + [participant.events, participant.room.events].emit(TrackUnsubscribedEvent( participant: participant, track: track!, publication: this, @@ -210,7 +213,7 @@ class RemoteTrackPublication trackSids: [sid], subscribe: subscribed, ); - participant.engine.signalClient.sendUpdateSubscription(subscription); + participant.room.engine.signalClient.sendUpdateSubscription(subscription); } void _sendUpdateTrackSettings() { @@ -221,6 +224,6 @@ class RemoteTrackPublication if (kind == lk_models.TrackType.VIDEO) { settings.quality = _videoQuality; } - participant.engine.signalClient.sendUpdateTrackSettings(settings); + participant.room.engine.signalClient.sendUpdateTrackSettings(settings); } } diff --git a/lib/src/room.dart b/lib/src/room.dart index 558e1db..9b30f0b 100644 --- a/lib/src/room.dart +++ b/lib/src/room.dart @@ -42,6 +42,10 @@ class Room extends DisposableChangeNotifier with EventsEmittable { UnmodifiableMapView get participants => UnmodifiableMapView(_participants); + ConnectOptions? connectOptions; + + RoomOptions? roomOptions; + /// the current participant LocalParticipant? localParticipant; @@ -57,15 +61,15 @@ class Room extends DisposableChangeNotifier with EventsEmittable { UnmodifiableListView get activeSpeakers => UnmodifiableListView(_activeSpeakers); - final RTCEngine engine; + late final engine = RTCEngine(room: this); // suppport for multiple event listeners late final _engineListener = engine.createListener(); Room({ - RTCEngine? engine, - ConnectOptions? connectOptions, - }) : engine = engine ?? RTCEngine() { + this.connectOptions, + this.roomOptions, + }) { // _setUpListeners(); @@ -83,21 +87,23 @@ class Room extends DisposableChangeNotifier with EventsEmittable { // dispose all listeners for RTCEngine await _engineListener.dispose(); // dispose the engine - await this.engine.dispose(); + await engine.dispose(); }); } Future connect( String url, String token, { - ConnectOptions? options, - RTCConfiguration? rtcConfig, + ConnectOptions? connectOptions, + RoomOptions? roomOptions, }) async { - // - final joinResponse = await engine.join( + // update options if provided + this.connectOptions = connectOptions ?? this.connectOptions; + this.roomOptions = roomOptions ?? this.roomOptions; + + final joinResponse = await engine.connect( url, token, - connectOptions: options, ); sid = joinResponse.room.sid; @@ -115,11 +121,8 @@ class Room extends DisposableChangeNotifier with EventsEmittable { ); localParticipant = LocalParticipant( - engine: engine, + room: this, info: joinResponse.participant, - defaultVideoPublishOptions: options?.defaultVideoPublishOptions, - defaultAudioPublishOptions: options?.defaultAudioPublishOptions, - roomEvents: events, ); for (final info in joinResponse.otherParticipants) { @@ -177,7 +180,7 @@ class Room extends DisposableChangeNotifier with EventsEmittable { ); } on TrackSubscriptionExceptionEvent catch (event) { logger.warning('addSubscribedMediaTrack() throwed ${event}'); - [participant.roomEvents, participant.events].emit(event); + [participant.room.events, participant.events].emit(event); } catch (exception) { // We don't want to pass up any exception so catch everything here. logger.warning( @@ -206,14 +209,13 @@ class Room extends DisposableChangeNotifier with EventsEmittable { if (info == null) { participant = RemoteParticipant( - engine: engine, + room: this, sid: sid, identity: '', - roomEvents: events, ); } else { participant = RemoteParticipant.fromInfo( - engine: engine, + room: this, info: info, roomEvents: events, ); diff --git a/lib/src/rtc_engine.dart b/lib/src/rtc_engine.dart index 125fce2..cc7a531 100644 --- a/lib/src/rtc_engine.dart +++ b/lib/src/rtc_engine.dart @@ -28,11 +28,10 @@ class RTCEngine extends Disposable with EventsEmittable { static const _reliableDCLabel = '_reliable'; static const _maxReconnectAttempts = 5; - final SignalClient signalClient; - // config for RTCPeerConnection - RTCConfiguration? rtcConfig; + // Reference to the Room + final Room room; - ConnectOptions connectOptions = const ConnectOptions(); + final SignalClient signalClient; @internal PCTransport? publisher; @@ -63,7 +62,7 @@ class RTCEngine extends Disposable with EventsEmittable { bool _subscriberPrimary = false; // server-provided ice servers - List _providedIceServers = []; + List _serverProvidedIceServers = []; // internal int _reconnectAttempts = 0; @@ -73,6 +72,7 @@ class RTCEngine extends Disposable with EventsEmittable { final delays = CancelableDelayManager(); RTCEngine({ + required this.room, SignalClient? signalClient, }) : signalClient = signalClient ?? SignalClient() { if (kDebugMode) { @@ -91,25 +91,18 @@ class RTCEngine extends Disposable with EventsEmittable { }); } - Future join( + Future connect( String url, - String token, { - RTCConfiguration? rtcConfig, - ConnectOptions? connectOptions, - }) async { + String token, + ) async { this.url = url; this.token = token; - this.rtcConfig = rtcConfig; - if (connectOptions != null) { - this.connectOptions = connectOptions; - } - // connect to rtc server await signalClient.connect( url, token, - options: this.connectOptions, + connectOptions: room.connectOptions, ); // wait for join response @@ -252,7 +245,11 @@ class RTCEngine extends Disposable with EventsEmittable { try { // isReconnecting = true; _connectionState = ConnectionState.reconnecting; - await signalClient.reconnect(url, token); + await signalClient.reconnect( + url, + token, + connectOptions: room.connectOptions, + ); if (publisher == null || subscriber == null) { throw UnexpectedStateException('publisher or subscribers is null'); @@ -294,17 +291,21 @@ class RTCEngine extends Disposable with EventsEmittable { return; } - RTCConfiguration? config; + // RTCConfiguration? config; // use server-provided iceServers if not provided by user - if ((rtcConfig?.iceServers?.isEmpty ?? true) && - _providedIceServers.isNotEmpty) { - final iceServers = _providedIceServers.map((e) => e.toSDKType()).toList(); - config = (rtcConfig ?? const RTCConfiguration()) - .copyWith(iceServers: iceServers); + final connectOptions = room.connectOptions ?? const ConnectOptions(); + final serverIceServers = + _serverProvidedIceServers.map((e) => e.toSDKType()).toList(); + + RTCConfiguration rtcConfiguration = connectOptions.rtcConfiguration; + if (serverIceServers.isNotEmpty) { + // use server provided iceServers if exists + rtcConfiguration = connectOptions.rtcConfiguration + .copyWith(iceServers: serverIceServers); } - publisher = await PCTransport.create(config); - subscriber = await PCTransport.create(config); + publisher = await PCTransport.create(rtcConfiguration); + subscriber = await PCTransport.create(rtcConfiguration); publisher?.pc.onIceCandidate = (rtc.RTCIceCandidate candidate) { logger.fine('publisher onIceCandidate'); @@ -497,7 +498,7 @@ class RTCEngine extends Disposable with EventsEmittable { // create peer connections _connectionState = ConnectionState.connected; _subscriberPrimary = event.response.subscriberPrimary; - _providedIceServers = event.response.iceServers; + _serverProvidedIceServers = event.response.iceServers; logger.fine('onConnected subscriberPrimary: ${_subscriberPrimary}, ' 'serverVersion: ${event.response.serverVersion}, ' diff --git a/lib/src/signal_client.dart b/lib/src/signal_client.dart index 80edb5c..1e63422 100644 --- a/lib/src/signal_client.dart +++ b/lib/src/signal_client.dart @@ -19,14 +19,10 @@ import 'utils.dart'; class SignalClient extends Disposable with EventsEmittable { // - final ProtocolVersion protocol; - bool _connected = false; LiveKitWebSocket? _ws; - SignalClient({ - this.protocol = ProtocolVersion.protocol5, - }) { + SignalClient() { events.listen((event) { logger.fine('[SignalEvent] $event'); }); @@ -42,13 +38,12 @@ class SignalClient extends Disposable with EventsEmittable { Future connect( String uriString, String token, { - required ConnectOptions options, + ConnectOptions? connectOptions, }) async { final rtcUri = Utils.buildUri( uriString, token: token, - options: options, - protocol: protocol, + connectOptions: connectOptions, ); try { @@ -65,10 +60,9 @@ class SignalClient extends Disposable with EventsEmittable { final validateUri = Utils.buildUri( uriString, token: token, - options: options, + connectOptions: connectOptions, validate: true, forceSecure: rtcUri.isSecureScheme, - protocol: protocol, ); // Attempt Validation @@ -89,8 +83,9 @@ class SignalClient extends Disposable with EventsEmittable { Future reconnect( String uriString, - String token, - ) async { + String token, { + ConnectOptions? connectOptions, + }) async { _connected = false; await _ws?.dispose(); _ws = null; @@ -99,7 +94,7 @@ class SignalClient extends Disposable with EventsEmittable { uriString, token: token, reconnect: true, - protocol: protocol, + connectOptions: connectOptions, ); _ws = await LiveKitWebSocket.connect( diff --git a/lib/src/track/web/_audio_html.dart b/lib/src/track/web/_audio_html.dart index 5117985..cde1b59 100644 --- a/lib/src/track/web/_audio_html.dart +++ b/lib/src/track/web/_audio_html.dart @@ -1,5 +1,4 @@ // ignore: avoid_web_libraries_in_flutter - import 'dart:html' as html; // ignore: implementation_imports diff --git a/lib/src/types.dart b/lib/src/types.dart index bae59b9..4b59b9c 100644 --- a/lib/src/types.dart +++ b/lib/src/types.dart @@ -5,10 +5,10 @@ import 'extensions.dart'; typedef CancelListenFunc = Function(); enum ProtocolVersion { - protocol2, - protocol3, - protocol4, - protocol5, + v2, + v3, + v4, + v5, } enum ConnectionState { diff --git a/lib/src/utils.dart b/lib/src/utils.dart index 09819a1..8f21dfc 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -6,7 +6,6 @@ import 'extensions.dart'; import 'livekit.dart'; import 'options.dart'; import 'track/options.dart'; -import 'types.dart'; extension UriExt on Uri { bool get isSecureScheme => ['https', 'wss'].contains(scheme); @@ -17,12 +16,13 @@ class Utils { static Uri buildUri( String uriString, { required String token, - ConnectOptions? options, + ConnectOptions? connectOptions, bool reconnect = false, bool validate = false, bool forceSecure = false, - required ProtocolVersion protocol, }) { + connectOptions ??= const ConnectOptions(); + final Uri uri = Uri.parse(uriString); final useSecure = uri.isSecureScheme || forceSecure; @@ -45,10 +45,9 @@ class Utils { pathSegments: pathSegments, queryParameters: { 'access_token': token, - if (options != null) - 'auto_subscribe': options.autoSubscribe ? '1' : '0', + 'auto_subscribe': connectOptions.autoSubscribe ? '1' : '0', if (reconnect) 'reconnect': '1', - 'protocol': protocol.toStringValue(), + 'protocol': connectOptions.protocolVersion.toStringValue(), 'sdk': 'flutter', 'version': LiveKitClient.version, },