Connection quality (#27)

* update protos

* signal event

* implemented

* format

* implement example

* protocol 5

* icon size
This commit is contained in:
Hiroshi Horie
2021-11-06 17:36:47 +09:00
committed by GitHub
parent 721b04753a
commit d31daa5d8e
17 changed files with 388 additions and 11 deletions
+19
View File
@@ -189,6 +189,18 @@ class ParticipantMetadataUpdatedEvent with RoomEvent, ParticipantEvent {
});
}
/// [Pariticpant]'s [ConnectionQuality] has updated.
/// Emitted by [Room] and [Participant].
class ParticipantConnectionQualityUpdatedEvent
with RoomEvent, ParticipantEvent {
final Participant participant;
final ConnectionQuality connectionQuality;
const ParticipantConnectionQualityUpdatedEvent({
required this.participant,
required this.connectionQuality,
});
}
/// Data received from [RemoteParticipant].
/// Data packets provides the ability to use LiveKit to send/receive arbitrary
/// payloads.
@@ -310,6 +322,13 @@ class SignalParticipantUpdateEvent with SignalEvent, EngineEvent {
});
}
class SignalConnectionQualityUpdateEvent with SignalEvent, EngineEvent {
final List<lk_rtc.ConnectionQualityInfo> updates;
const SignalConnectionQualityUpdateEvent({
required this.updates,
});
}
class SignalLocalTrackPublishedEvent with SignalEvent {
final String cid;
final lk_models.TrackInfo track;
+11
View File
@@ -41,6 +41,7 @@ extension ProtocolVersionExt on ProtocolVersion {
ProtocolVersion.protocol2: '2',
ProtocolVersion.protocol3: '3',
ProtocolVersion.protocol4: '4',
ProtocolVersion.protocol5: '5',
}[this]!;
}
@@ -91,3 +92,13 @@ extension SessionDescriptionExt on lk_rtc.SessionDescription {
return rtc.RTCSessionDescription(sdp, type);
}
}
extension ConnectionQualityExt on lk_models.ConnectionQuality {
ConnectionQuality toLKType() =>
{
lk_models.ConnectionQuality.POOR: ConnectionQuality.poor,
lk_models.ConnectionQuality.GOOD: ConnectionQuality.good,
lk_models.ConnectionQuality.EXCELLENT: ConnectionQuality.excellent,
}[this] ??
ConnectionQuality.unknown;
}
+16
View File
@@ -8,6 +8,7 @@ import '../managers/event.dart';
import '../proto/livekit_models.pb.dart' as lk_models;
import '../support/disposable.dart';
import '../track/track_publication.dart';
import '../types.dart';
import 'remote_participant.dart';
/// Represents a Participant in the room, notifies changes via delegates as
@@ -43,6 +44,8 @@ abstract class Participant extends DisposableChangeNotifier
lk_models.ParticipantInfo? _participantInfo;
bool _isSpeaking = false;
ConnectionQuality _connectionQuality = ConnectionQuality.unknown;
// suppport for multiple event listeners
final EventsEmitter<RoomEvent> roomEvents;
@@ -66,6 +69,9 @@ abstract class Participant extends DisposableChangeNotifier
bool get hasVideo => videoTracks.isNotEmpty;
/// Connection quality of the participant
ConnectionQuality get connectionQuality => _connectionQuality;
/// tracks that are subscribed to
List<TrackPublication> get subscribedTracks =>
trackPublications.values.where((e) => e.subscribed).toList();
@@ -120,6 +126,16 @@ abstract class Participant extends DisposableChangeNotifier
}
}
@internal
void updateConnectionQuality(ConnectionQuality quality) {
if (_connectionQuality == quality) return;
_connectionQuality = quality;
[events, roomEvents].emit(ParticipantConnectionQualityUpdatedEvent(
participant: this,
connectionQuality: _connectionQuality,
));
}
/// for internal use
/// {@nodoc}
@internal
+1 -1
View File
@@ -3,7 +3,7 @@
// source: livekit_models.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name
// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name
import 'dart:core' as $core;
+31 -1
View File
@@ -3,7 +3,7 @@
// source: livekit_models.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name
// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name
// ignore_for_file: UNDEFINED_SHOWN_NAME
import 'dart:core' as $core;
@@ -75,6 +75,36 @@ class TrackSource extends $pb.ProtobufEnum {
const TrackSource._($core.int v, $core.String n) : super(v, n);
}
class ConnectionQuality extends $pb.ProtobufEnum {
static const ConnectionQuality POOR = ConnectionQuality._(
0,
const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? ''
: 'POOR');
static const ConnectionQuality GOOD = ConnectionQuality._(
1,
const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? ''
: 'GOOD');
static const ConnectionQuality EXCELLENT = ConnectionQuality._(
2,
const $core.bool.fromEnvironment('protobuf.omit_enum_names')
? ''
: 'EXCELLENT');
static const $core.List<ConnectionQuality> values = <ConnectionQuality>[
POOR,
GOOD,
EXCELLENT,
];
static final $core.Map<$core.int, ConnectionQuality> _byValue =
$pb.ProtobufEnum.initByValue(values);
static ConnectionQuality? valueOf($core.int value) => _byValue[value];
const ConnectionQuality._($core.int v, $core.String n) : super(v, n);
}
class ParticipantInfo_State extends $pb.ProtobufEnum {
static const ParticipantInfo_State JOINING = ParticipantInfo_State._(
0,
+14 -1
View File
@@ -3,7 +3,7 @@
// source: livekit_models.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name
// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name
import 'dart:core' as $core;
import 'dart:convert' as $convert;
@@ -36,6 +36,19 @@ const TrackSource$json = const {
/// Descriptor for `TrackSource`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List trackSourceDescriptor = $convert.base64Decode(
'CgtUcmFja1NvdXJjZRILCgdVTktOT1dOEAASCgoGQ0FNRVJBEAESDgoKTUlDUk9QSE9ORRACEhAKDFNDUkVFTl9TSEFSRRAD');
@$core.Deprecated('Use connectionQualityDescriptor instead')
const ConnectionQuality$json = const {
'1': 'ConnectionQuality',
'2': const [
const {'1': 'POOR', '2': 0},
const {'1': 'GOOD', '2': 1},
const {'1': 'EXCELLENT', '2': 2},
],
};
/// Descriptor for `ConnectionQuality`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List connectionQualityDescriptor = $convert.base64Decode(
'ChFDb25uZWN0aW9uUXVhbGl0eRIICgRQT09SEAASCAoER09PRBABEg0KCUVYQ0VMTEVOVBAC');
@$core.Deprecated('Use roomDescriptor instead')
const Room$json = const {
'1': 'Room',
+1 -1
View File
@@ -3,6 +3,6 @@
// source: livekit_models.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name
// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name
export 'livekit_models.pb.dart';
+184 -2
View File
@@ -3,7 +3,7 @@
// source: livekit_rtc.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name
// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name
import 'dart:core' as $core;
@@ -294,6 +294,7 @@ enum SignalResponse_Message {
mute,
speakersChanged,
roomUpdate,
connectionQuality,
notSet
}
@@ -310,6 +311,7 @@ class SignalResponse extends $pb.GeneratedMessage {
9: SignalResponse_Message.mute,
10: SignalResponse_Message.speakersChanged,
11: SignalResponse_Message.roomUpdate,
12: SignalResponse_Message.connectionQuality,
0: SignalResponse_Message.notSet
};
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
@@ -321,7 +323,7 @@ class SignalResponse extends $pb.GeneratedMessage {
? ''
: 'livekit'),
createEmptyInstance: create)
..oo(0, [1, 2, 3, 4, 5, 6, 8, 9, 10, 11])
..oo(0, [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12])
..aOM<JoinResponse>(
1,
const $core.bool.fromEnvironment('protobuf.omit_field_names')
@@ -382,6 +384,12 @@ class SignalResponse extends $pb.GeneratedMessage {
? ''
: 'roomUpdate',
subBuilder: RoomUpdate.create)
..aOM<ConnectionQualityUpdate>(
12,
const $core.bool.fromEnvironment('protobuf.omit_field_names')
? ''
: 'connectionQuality',
subBuilder: ConnectionQualityUpdate.create)
..hasRequiredFields = false;
SignalResponse._() : super();
@@ -396,6 +404,7 @@ class SignalResponse extends $pb.GeneratedMessage {
MuteTrackRequest? mute,
SpeakersChanged? speakersChanged,
RoomUpdate? roomUpdate,
ConnectionQualityUpdate? connectionQuality,
}) {
final _result = create();
if (join != null) {
@@ -428,6 +437,9 @@ class SignalResponse extends $pb.GeneratedMessage {
if (roomUpdate != null) {
_result.roomUpdate = roomUpdate;
}
if (connectionQuality != null) {
_result.connectionQuality = connectionQuality;
}
return _result;
}
factory SignalResponse.fromBuffer($core.List<$core.int> i,
@@ -600,6 +612,20 @@ class SignalResponse extends $pb.GeneratedMessage {
void clearRoomUpdate() => clearField(11);
@$pb.TagNumber(11)
RoomUpdate ensureRoomUpdate() => $_ensure(9);
@$pb.TagNumber(12)
ConnectionQualityUpdate get connectionQuality => $_getN(10);
@$pb.TagNumber(12)
set connectionQuality(ConnectionQualityUpdate v) {
setField(12, v);
}
@$pb.TagNumber(12)
$core.bool hasConnectionQuality() => $_has(10);
@$pb.TagNumber(12)
void clearConnectionQuality() => clearField(12);
@$pb.TagNumber(12)
ConnectionQualityUpdate ensureConnectionQuality() => $_ensure(10);
}
class AddTrackRequest extends $pb.GeneratedMessage {
@@ -1954,3 +1980,159 @@ class RoomUpdate extends $pb.GeneratedMessage {
@$pb.TagNumber(1)
$0.Room ensureRoom() => $_ensure(0);
}
class ConnectionQualityInfo extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
const $core.bool.fromEnvironment('protobuf.omit_message_names')
? ''
: 'ConnectionQualityInfo',
package: const $pb.PackageName(
const $core.bool.fromEnvironment('protobuf.omit_message_names')
? ''
: 'livekit'),
createEmptyInstance: create)
..aOS(
1,
const $core.bool.fromEnvironment('protobuf.omit_field_names')
? ''
: 'participantSid')
..e<$0.ConnectionQuality>(
2,
const $core.bool.fromEnvironment('protobuf.omit_field_names')
? ''
: 'quality',
$pb.PbFieldType.OE,
defaultOrMaker: $0.ConnectionQuality.POOR,
valueOf: $0.ConnectionQuality.valueOf,
enumValues: $0.ConnectionQuality.values)
..hasRequiredFields = false;
ConnectionQualityInfo._() : super();
factory ConnectionQualityInfo({
$core.String? participantSid,
$0.ConnectionQuality? quality,
}) {
final _result = create();
if (participantSid != null) {
_result.participantSid = participantSid;
}
if (quality != null) {
_result.quality = quality;
}
return _result;
}
factory ConnectionQualityInfo.fromBuffer($core.List<$core.int> i,
[$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(i, r);
factory ConnectionQualityInfo.fromJson($core.String i,
[$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(i, r);
@$core.Deprecated('Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
ConnectionQualityInfo clone() =>
ConnectionQualityInfo()..mergeFromMessage(this);
@$core.Deprecated('Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
ConnectionQualityInfo copyWith(
void Function(ConnectionQualityInfo) updates) =>
super.copyWith((message) => updates(message as ConnectionQualityInfo))
as ConnectionQualityInfo; // ignore: deprecated_member_use
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static ConnectionQualityInfo create() => ConnectionQualityInfo._();
ConnectionQualityInfo createEmptyInstance() => create();
static $pb.PbList<ConnectionQualityInfo> createRepeated() =>
$pb.PbList<ConnectionQualityInfo>();
@$core.pragma('dart2js:noInline')
static ConnectionQualityInfo getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<ConnectionQualityInfo>(create);
static ConnectionQualityInfo? _defaultInstance;
@$pb.TagNumber(1)
$core.String get participantSid => $_getSZ(0);
@$pb.TagNumber(1)
set participantSid($core.String v) {
$_setString(0, v);
}
@$pb.TagNumber(1)
$core.bool hasParticipantSid() => $_has(0);
@$pb.TagNumber(1)
void clearParticipantSid() => clearField(1);
@$pb.TagNumber(2)
$0.ConnectionQuality get quality => $_getN(1);
@$pb.TagNumber(2)
set quality($0.ConnectionQuality v) {
setField(2, v);
}
@$pb.TagNumber(2)
$core.bool hasQuality() => $_has(1);
@$pb.TagNumber(2)
void clearQuality() => clearField(2);
}
class ConnectionQualityUpdate extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
const $core.bool.fromEnvironment('protobuf.omit_message_names')
? ''
: 'ConnectionQualityUpdate',
package: const $pb.PackageName(
const $core.bool.fromEnvironment('protobuf.omit_message_names')
? ''
: 'livekit'),
createEmptyInstance: create)
..pc<ConnectionQualityInfo>(
1,
const $core.bool.fromEnvironment('protobuf.omit_field_names')
? ''
: 'updates',
$pb.PbFieldType.PM,
subBuilder: ConnectionQualityInfo.create)
..hasRequiredFields = false;
ConnectionQualityUpdate._() : super();
factory ConnectionQualityUpdate({
$core.Iterable<ConnectionQualityInfo>? updates,
}) {
final _result = create();
if (updates != null) {
_result.updates.addAll(updates);
}
return _result;
}
factory ConnectionQualityUpdate.fromBuffer($core.List<$core.int> i,
[$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(i, r);
factory ConnectionQualityUpdate.fromJson($core.String i,
[$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(i, r);
@$core.Deprecated('Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
ConnectionQualityUpdate clone() =>
ConnectionQualityUpdate()..mergeFromMessage(this);
@$core.Deprecated('Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
ConnectionQualityUpdate copyWith(
void Function(ConnectionQualityUpdate) updates) =>
super.copyWith((message) => updates(message as ConnectionQualityUpdate))
as ConnectionQualityUpdate; // ignore: deprecated_member_use
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static ConnectionQualityUpdate create() => ConnectionQualityUpdate._();
ConnectionQualityUpdate createEmptyInstance() => create();
static $pb.PbList<ConnectionQualityUpdate> createRepeated() =>
$pb.PbList<ConnectionQualityUpdate>();
@$core.pragma('dart2js:noInline')
static ConnectionQualityUpdate getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<ConnectionQualityUpdate>(create);
static ConnectionQualityUpdate? _defaultInstance;
@$pb.TagNumber(1)
$core.List<ConnectionQualityInfo> get updates => $_getList(0);
}
+1 -1
View File
@@ -3,7 +3,7 @@
// source: livekit_rtc.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name
// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name
// ignore_for_file: UNDEFINED_SHOWN_NAME
import 'dart:core' as $core;
+55 -2
View File
@@ -3,7 +3,7 @@
// source: livekit_rtc.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name
// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name
import 'dart:core' as $core;
import 'dart:convert' as $convert;
@@ -213,6 +213,15 @@ const SignalResponse$json = const {
'9': 0,
'10': 'roomUpdate'
},
const {
'1': 'connection_quality',
'3': 12,
'4': 1,
'5': 11,
'6': '.livekit.ConnectionQualityUpdate',
'9': 0,
'10': 'connectionQuality'
},
],
'8': const [
const {'1': 'message'},
@@ -221,7 +230,7 @@ const SignalResponse$json = const {
/// Descriptor for `SignalResponse`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List signalResponseDescriptor = $convert.base64Decode(
'Cg5TaWduYWxSZXNwb25zZRIrCgRqb2luGAEgASgLMhUubGl2ZWtpdC5Kb2luUmVzcG9uc2VIAFIEam9pbhI1CgZhbnN3ZXIYAiABKAsyGy5saXZla2l0LlNlc3Npb25EZXNjcmlwdGlvbkgAUgZhbnN3ZXISMwoFb2ZmZXIYAyABKAsyGy5saXZla2l0LlNlc3Npb25EZXNjcmlwdGlvbkgAUgVvZmZlchIzCgd0cmlja2xlGAQgASgLMhcubGl2ZWtpdC5Ucmlja2xlUmVxdWVzdEgAUgd0cmlja2xlEjQKBnVwZGF0ZRgFIAEoCzIaLmxpdmVraXQuUGFydGljaXBhbnRVcGRhdGVIAFIGdXBkYXRlEkoKD3RyYWNrX3B1Ymxpc2hlZBgGIAEoCzIfLmxpdmVraXQuVHJhY2tQdWJsaXNoZWRSZXNwb25zZUgAUg50cmFja1B1Ymxpc2hlZBItCgVsZWF2ZRgIIAEoCzIVLmxpdmVraXQuTGVhdmVSZXF1ZXN0SABSBWxlYXZlEi8KBG11dGUYCSABKAsyGS5saXZla2l0Lk11dGVUcmFja1JlcXVlc3RIAFIEbXV0ZRJFChBzcGVha2Vyc19jaGFuZ2VkGAogASgLMhgubGl2ZWtpdC5TcGVha2Vyc0NoYW5nZWRIAFIPc3BlYWtlcnNDaGFuZ2VkEjYKC3Jvb21fdXBkYXRlGAsgASgLMhMubGl2ZWtpdC5Sb29tVXBkYXRlSABSCnJvb21VcGRhdGVCCQoHbWVzc2FnZQ==');
'Cg5TaWduYWxSZXNwb25zZRIrCgRqb2luGAEgASgLMhUubGl2ZWtpdC5Kb2luUmVzcG9uc2VIAFIEam9pbhI1CgZhbnN3ZXIYAiABKAsyGy5saXZla2l0LlNlc3Npb25EZXNjcmlwdGlvbkgAUgZhbnN3ZXISMwoFb2ZmZXIYAyABKAsyGy5saXZla2l0LlNlc3Npb25EZXNjcmlwdGlvbkgAUgVvZmZlchIzCgd0cmlja2xlGAQgASgLMhcubGl2ZWtpdC5Ucmlja2xlUmVxdWVzdEgAUgd0cmlja2xlEjQKBnVwZGF0ZRgFIAEoCzIaLmxpdmVraXQuUGFydGljaXBhbnRVcGRhdGVIAFIGdXBkYXRlEkoKD3RyYWNrX3B1Ymxpc2hlZBgGIAEoCzIfLmxpdmVraXQuVHJhY2tQdWJsaXNoZWRSZXNwb25zZUgAUg50cmFja1B1Ymxpc2hlZBItCgVsZWF2ZRgIIAEoCzIVLmxpdmVraXQuTGVhdmVSZXF1ZXN0SABSBWxlYXZlEi8KBG11dGUYCSABKAsyGS5saXZla2l0Lk11dGVUcmFja1JlcXVlc3RIAFIEbXV0ZRJFChBzcGVha2Vyc19jaGFuZ2VkGAogASgLMhgubGl2ZWtpdC5TcGVha2Vyc0NoYW5nZWRIAFIPc3BlYWtlcnNDaGFuZ2VkEjYKC3Jvb21fdXBkYXRlGAsgASgLMhMubGl2ZWtpdC5Sb29tVXBkYXRlSABSCnJvb21VcGRhdGUSUQoSY29ubmVjdGlvbl9xdWFsaXR5GAwgASgLMiAubGl2ZWtpdC5Db25uZWN0aW9uUXVhbGl0eVVwZGF0ZUgAUhFjb25uZWN0aW9uUXVhbGl0eUIJCgdtZXNzYWdl');
@$core.Deprecated('Use addTrackRequestDescriptor instead')
const AddTrackRequest$json = const {
'1': 'AddTrackRequest',
@@ -492,3 +501,47 @@ const RoomUpdate$json = const {
/// Descriptor for `RoomUpdate`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List roomUpdateDescriptor = $convert.base64Decode(
'CgpSb29tVXBkYXRlEiEKBHJvb20YASABKAsyDS5saXZla2l0LlJvb21SBHJvb20=');
@$core.Deprecated('Use connectionQualityInfoDescriptor instead')
const ConnectionQualityInfo$json = const {
'1': 'ConnectionQualityInfo',
'2': const [
const {
'1': 'participant_sid',
'3': 1,
'4': 1,
'5': 9,
'10': 'participantSid'
},
const {
'1': 'quality',
'3': 2,
'4': 1,
'5': 14,
'6': '.livekit.ConnectionQuality',
'10': 'quality'
},
],
};
/// Descriptor for `ConnectionQualityInfo`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List connectionQualityInfoDescriptor = $convert.base64Decode(
'ChVDb25uZWN0aW9uUXVhbGl0eUluZm8SJwoPcGFydGljaXBhbnRfc2lkGAEgASgJUg5wYXJ0aWNpcGFudFNpZBI0CgdxdWFsaXR5GAIgASgOMhoubGl2ZWtpdC5Db25uZWN0aW9uUXVhbGl0eVIHcXVhbGl0eQ==');
@$core.Deprecated('Use connectionQualityUpdateDescriptor instead')
const ConnectionQualityUpdate$json = const {
'1': 'ConnectionQualityUpdate',
'2': const [
const {
'1': 'updates',
'3': 1,
'4': 3,
'5': 11,
'6': '.livekit.ConnectionQualityInfo',
'10': 'updates'
},
],
};
/// Descriptor for `ConnectionQualityUpdate`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List connectionQualityUpdateDescriptor =
$convert.base64Decode(
'ChdDb25uZWN0aW9uUXVhbGl0eVVwZGF0ZRI4Cgd1cGRhdGVzGAEgAygLMh4ubGl2ZWtpdC5Db25uZWN0aW9uUXVhbGl0eUluZm9SB3VwZGF0ZXM=');
+1 -1
View File
@@ -3,6 +3,6 @@
// source: livekit_rtc.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_this,unused_import,unused_shown_name
// ignore_for_file: annotate_overrides,camel_case_types,constant_identifier_names,deprecated_member_use_from_same_package,directives_ordering,library_prefixes,non_constant_identifier_names,prefer_final_fields,return_of_invalid_type,unnecessary_const,unnecessary_import,unnecessary_this,unused_import,unused_shown_name
export 'livekit_rtc.pb.dart';
+19
View File
@@ -174,6 +174,8 @@ class Room extends DisposableChangeNotifier with EventsEmittable<RoomEvent> {
(event) => _onEngineActiveSpeakersUpdateEvent(event.speakers))
..on<SignalSpeakersChangedEvent>(
(event) => _onSignalSpeakersChangedEvent(event.speakers))
..on<SignalConnectionQualityUpdateEvent>(
(event) => _onSignalConnectionQualityUpdateEvent(event.updates))
..on<EngineDataPacketReceivedEvent>(_onDataMessageEvent)
..on<EngineRemoteMuteChangedEvent>((event) async {
final track = localParticipant.trackPublications[event.sid];
@@ -366,6 +368,23 @@ class Room extends DisposableChangeNotifier with EventsEmittable<RoomEvent> {
events.emit(ActiveSpeakersChangedEvent(speakers: activeSpeakers));
}
void _onSignalConnectionQualityUpdateEvent(
List<lk_rtc.ConnectionQualityInfo> updates) {
for (final entry in updates) {
Participant? participant;
if (entry.participantSid == localParticipant.sid) {
participant = localParticipant;
} else {
participant = _participants[entry.participantSid];
}
if (participant != null) {
// update the connection quality if the participant is found
participant.updateConnectionQuality(entry.quality.toLKType());
}
}
}
void _onDataMessageEvent(EngineDataPacketReceivedEvent dataPacketEvent) {
// participant may be null if data is sent from Server-API
final senderSid = dataPacketEvent.packet.participantSid;
+2
View File
@@ -550,6 +550,8 @@ class RTCEngine extends Disposable with EventsEmittable<EngineEvent> {
..on<SignalParticipantUpdateEvent>((event) => events.emit(event))
// relay
..on<SignalSpeakersChangedEvent>((event) => events.emit(event))
// relay
..on<SignalConnectionQualityUpdateEvent>((event) => events.emit(event))
..on<SignalLeaveEvent>((event) async {
await close();
events.emit(const EngineDisconnectedEvent());
+6 -1
View File
@@ -24,7 +24,7 @@ class SignalClient extends Disposable with EventsEmittable<SignalEvent> {
LiveKitWebSocket? _ws;
SignalClient({
this.protocol = ProtocolVersion.protocol4,
this.protocol = ProtocolVersion.protocol5,
}) {
events.listen((event) {
logger.fine('[SignalEvent] $event');
@@ -247,6 +247,11 @@ class SignalClient extends Disposable with EventsEmittable<SignalEvent> {
events.emit(
SignalSpeakersChangedEvent(speakers: msg.speakersChanged.speakers));
break;
case lk_rtc.SignalResponse_Message.connectionQuality:
events.emit(SignalConnectionQualityUpdateEvent(
updates: msg.connectionQuality.updates,
));
break;
case lk_rtc.SignalResponse_Message.leave:
events.emit(SignalLeaveEvent(canReconnect: msg.leave.canReconnect));
break;
+8
View File
@@ -8,6 +8,7 @@ enum ProtocolVersion {
protocol2,
protocol3,
protocol4,
protocol5,
}
enum ConnectionState {
@@ -16,6 +17,13 @@ enum ConnectionState {
reconnecting,
}
enum ConnectionQuality {
unknown,
poor,
good,
excellent,
}
enum Reliability {
reliable,
lossy,