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