From 48754e167226c31dfa8562c76a9610f436cf2330 Mon Sep 17 00:00:00 2001 From: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> Date: Mon, 4 Apr 2022 16:09:15 +0900 Subject: [PATCH] [Protocol v7] Remote unpublish & expose permissions (#101) * fix * impl * oldPermissions * mods --- lib/src/core/room.dart | 4 +++ lib/src/core/signal_client.dart | 5 ++++ lib/src/events.dart | 19 ++++++++++++++ lib/src/extensions.dart | 1 + lib/src/internal/events.dart | 9 +++++++ lib/src/options.dart | 2 +- lib/src/participant/local.dart | 17 +++++++++++- lib/src/participant/participant.dart | 14 ++++++++++ lib/src/types/other.dart | 1 + lib/src/types/participant_permissions.dart | 30 ++++++++++++++++++++++ 10 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 lib/src/types/participant_permissions.dart diff --git a/lib/src/core/room.dart b/lib/src/core/room.dart index 3f3c84e..1fd102e 100644 --- a/lib/src/core/room.dart +++ b/lib/src/core/room.dart @@ -211,6 +211,10 @@ class Room extends DisposableChangeNotifier with EventsEmittable { } else { await publication?.unmute(); } + }) + ..on((event) async { + // unpublish local track + await localParticipant?.unpublishTrack(event.trackSid); }); void _setUpEngineListeners() => _engineListener diff --git a/lib/src/core/signal_client.dart b/lib/src/core/signal_client.dart index c7ed5dc..1454a1c 100644 --- a/lib/src/core/signal_client.dart +++ b/lib/src/core/signal_client.dart @@ -170,6 +170,11 @@ class SignalClient extends Disposable with EventsEmittable { track: msg.trackPublished.track, )); break; + case lk_rtc.SignalResponse_Message.trackUnpublished: + events.emit(SignalTrackUnpublishedEvent( + trackSid: msg.trackUnpublished.trackSid, + )); + break; case lk_rtc.SignalResponse_Message.speakersChanged: events.emit( SignalSpeakersChangedEvent(speakers: msg.speakersChanged.speakers)); diff --git a/lib/src/events.dart b/lib/src/events.dart index efaaed8..05d5073 100644 --- a/lib/src/events.dart +++ b/lib/src/events.dart @@ -9,6 +9,7 @@ import 'publication/remote.dart'; import 'publication/track_publication.dart'; import 'track/track.dart'; import 'types/other.dart'; +import 'types/participant_permissions.dart'; /// Base type for all LiveKit events. mixin LiveKitEvent {} @@ -360,3 +361,21 @@ class TrackSubscriptionPermissionChangedEvent with RoomEvent, ParticipantEvent { '(participant: ${participant}, publication: ${publication}, ' 'state: ${state})'; } + +/// The [ParticipantPermissions] updated for the [Participant]. +/// Currently, only for [LocalParticipant]. +/// Emitted by [Room] and [LocalParticipant]. +class ParticipantPermissionsUpdatedEvent with RoomEvent, ParticipantEvent { + final Participant participant; + final ParticipantPermissions permissions; + final ParticipantPermissions oldPermissions; + const ParticipantPermissionsUpdatedEvent({ + required this.participant, + required this.permissions, + required this.oldPermissions, + }); + + @override + String toString() => '${runtimeType}' + '(participant: ${participant}, permissions: ${permissions})'; +} diff --git a/lib/src/extensions.dart b/lib/src/extensions.dart index 0c0f7e1..80ac9e2 100644 --- a/lib/src/extensions.dart +++ b/lib/src/extensions.dart @@ -43,6 +43,7 @@ extension ProtocolVersionExt on ProtocolVersion { ProtocolVersion.v4: '4', ProtocolVersion.v5: '5', ProtocolVersion.v6: '6', + ProtocolVersion.v7: '7', }[this]!; } diff --git a/lib/src/internal/events.dart b/lib/src/internal/events.dart index 6fadc8b..7b223a0 100644 --- a/lib/src/internal/events.dart +++ b/lib/src/internal/events.dart @@ -194,6 +194,15 @@ class SignalLocalTrackPublishedEvent with SignalEvent, InternalEvent { }); } +@internal +class SignalTrackUnpublishedEvent with SignalEvent, InternalEvent { + final String trackSid; + + const SignalTrackUnpublishedEvent({ + required this.trackSid, + }); +} + @internal class SignalRoomUpdateEvent with SignalEvent, InternalEvent { final lk_models.Room room; diff --git a/lib/src/options.dart b/lib/src/options.dart index 33a8e6e..30e115b 100644 --- a/lib/src/options.dart +++ b/lib/src/options.dart @@ -24,7 +24,7 @@ class ConnectOptions { const ConnectOptions({ this.autoSubscribe = true, this.rtcConfiguration = const RTCConfiguration(), - this.protocolVersion = ProtocolVersion.v6, + this.protocolVersion = ProtocolVersion.v7, }); } diff --git a/lib/src/participant/local.dart b/lib/src/participant/local.dart index d76fb14..248a82c 100644 --- a/lib/src/participant/local.dart +++ b/lib/src/participant/local.dart @@ -1,5 +1,4 @@ import 'package:flutter/foundation.dart'; - import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; import 'package:meta/meta.dart'; @@ -17,6 +16,7 @@ import '../track/local/audio.dart'; import '../track/local/local.dart'; import '../track/local/video.dart'; import '../types/other.dart'; +import '../types/participant_permissions.dart'; import '../types/video_dimensions.dart'; import '../utils.dart'; import 'participant.dart'; @@ -339,4 +339,19 @@ class LocalParticipant extends Participant { @internal Iterable publishedTracksInfo() => trackPublications.values.map((e) => e.toPBTrackPublishedResponse()); + + @internal + @override + ParticipantPermissions? setPermissions(ParticipantPermissions newValue) { + final oldValue = super.setPermissions(newValue); + if (oldValue != null) { + // notify + [events, room.events].emit(ParticipantPermissionsUpdatedEvent( + participant: this, + permissions: newValue, + oldPermissions: oldValue, + )); + } + return oldValue; + } } diff --git a/lib/src/participant/participant.dart b/lib/src/participant/participant.dart index c6090e7..aa9dbaa 100644 --- a/lib/src/participant/participant.dart +++ b/lib/src/participant/participant.dart @@ -12,6 +12,7 @@ import '../support/disposable.dart'; import '../track/local/local.dart'; import '../track/track.dart'; import '../types/other.dart'; +import '../types/participant_permissions.dart'; import 'local.dart'; import 'remote.dart'; @@ -59,6 +60,9 @@ abstract class Participant /// Connection quality between the [Participant] and the server. ConnectionQuality _connectionQuality = ConnectionQuality.unknown; + ParticipantPermissions _permissions = const ParticipantPermissions(); + ParticipantPermissions get permissions => _permissions; + /// when the participant joined the room DateTime get joinedAt { final pi = _participantInfo; @@ -161,6 +165,16 @@ abstract class Participant _setMetadata(info.metadata); } _participantInfo = info; + setPermissions(info.permission.toLKType()); + } + + @internal + // returns oldValue (if updated) + ParticipantPermissions? setPermissions(ParticipantPermissions newValue) { + if (_permissions == newValue) return null; + final oldValue = _permissions; + _permissions = newValue; + return oldValue; } /// for internal use diff --git a/lib/src/types/other.dart b/lib/src/types/other.dart index 918db86..369d82c 100644 --- a/lib/src/types/other.dart +++ b/lib/src/types/other.dart @@ -13,6 +13,7 @@ enum ProtocolVersion { v4, v5, v6, // Session migration + v7, // Remote unpublish } /// Connection state type used throughout the SDK. diff --git a/lib/src/types/participant_permissions.dart b/lib/src/types/participant_permissions.dart new file mode 100644 index 0000000..f8f2b7a --- /dev/null +++ b/lib/src/types/participant_permissions.dart @@ -0,0 +1,30 @@ +import 'package:meta/meta.dart'; + +import '../proto/livekit_models.pb.dart' as lk_models; + +@immutable +class ParticipantPermissions { + final bool canSubscribe; + final bool canPublish; + final bool canPublishData; + final bool hidden; + final bool recorder; + + const ParticipantPermissions({ + this.canSubscribe = false, + this.canPublish = false, + this.canPublishData = false, + this.hidden = false, + this.recorder = false, + }); +} + +extension ParticipantPermissionExt on lk_models.ParticipantPermission { + ParticipantPermissions toLKType() => ParticipantPermissions( + canSubscribe: canSubscribe, + canPublish: canPublish, + canPublishData: canPublishData, + hidden: hidden, + recorder: recorder, + ); +}