22using System . Linq ;
33using System . Collections . Generic ;
44using System . Threading . Tasks ;
5- using Google . Protobuf . Collections ;
65using LiveKit . Internal ;
76using LiveKit . Proto ;
87using LiveKit . Internal . FFIClients . Requests ;
@@ -16,15 +15,15 @@ public class Participant
1615 {
1716 public delegate void PublishDelegate ( RemoteTrackPublication publication ) ;
1817
19-
20- private ParticipantInfo _info ;
18+ internal ParticipantInfo _info ; // Can be updated by the server through room events.
2119 internal readonly Dictionary < string , TrackPublication > _tracks = new ( ) ;
2220 public FfiHandle Handle ;
2321 public string Sid => _info . Sid ;
2422 public string Identity => _info . Identity ;
2523 public string Name => _info . Name ;
2624 public string Metadata => _info . Metadata ;
27- public MapField < string , string > Attributes => _info . Attributes ;
25+ public IReadOnlyDictionary < string , string > Attributes => _info . Attributes ;
26+
2827 public ConnectionQuality ConnectionQuality { internal set ; get ; }
2928 public event PublishDelegate TrackPublished ;
3029 public event PublishDelegate TrackUnpublished ;
@@ -38,23 +37,14 @@ protected Participant(OwnedParticipant participant, Room room)
3837 {
3938 Room = new WeakReference < Room > ( room ) ;
4039 Handle = FfiHandle . FromOwnedHandle ( participant . Handle ) ;
41- UpdateInfo ( participant . Info ) ;
40+ _info = participant . Info ;
4241 }
4342
44- public void SetMeta ( string meta )
45- {
46- _info . Metadata = meta ;
47- }
43+ [ Obsolete ( "Use SetMetadata on LocalParticipant instead; this method has no effect" ) ]
44+ public void SetMeta ( string meta ) { }
4845
49- public void SetName ( string name )
50- {
51- _info . Name = name ;
52- }
53-
54- internal void UpdateInfo ( ParticipantInfo info )
55- {
56- _info = info ;
57- }
46+ [ Obsolete ( "Use SetName on LocalParticipant instead; this method has no effect" ) ]
47+ public void SetName ( string name ) { }
5848
5949 internal void OnTrackPublished ( RemoteTrackPublication publication )
6050 {
@@ -65,7 +55,6 @@ internal void OnTrackUnpublished(RemoteTrackPublication publication)
6555 {
6656 TrackUnpublished ? . Invoke ( publication ) ;
6757 }
68-
6958 }
7059
7160 public sealed class LocalParticipant : Participant
@@ -124,22 +113,91 @@ public void PublishData(Span<byte> data, IReadOnlyCollection<string> destination
124113 }
125114 }
126115
116+ [ Obsolete ( "Use SetMetadata instead" ) ]
127117 public void UpdateMetadata ( string metadata )
128118 {
129- using var request = FFIBridge . Instance . NewRequest < SetLocalMetadataRequest > ( ) ;
130- var updateReq = request . request ;
131- updateReq . Metadata = metadata ;
132- var resp = request . Send ( ) ;
119+ SetMetadata ( metadata ) ;
133120 }
134121
122+ [ Obsolete ( "Use SetName instead" ) ]
135123 public void UpdateName ( string name )
124+ {
125+ SetName ( name ) ;
126+ }
127+
128+ /// <summary>
129+ /// Set the metadata for the local participant.
130+ /// </summary>
131+ /// <remarks>
132+ /// This requires `canUpdateOwnMetadata` permission.
133+ /// </remarks>
134+ /// <param name="metadata">The new metadata.</param>
135+ public SetLocalMetadataInstruction SetMetadata ( string metadata )
136+ {
137+ using var request = FFIBridge . Instance . NewRequest < SetLocalMetadataRequest > ( ) ;
138+ var setReq = request . request ;
139+ setReq . LocalParticipantHandle = ( ulong ) Handle . DangerousGetHandle ( ) ;
140+ setReq . Metadata = metadata ;
141+
142+ using var response = request . Send ( ) ;
143+ FfiResponse res = response ;
144+ return new SetLocalMetadataInstruction ( res . SetLocalMetadata . AsyncId ) ;
145+ }
146+
147+ /// <summary>
148+ /// Set the name for the local participant.
149+ /// </summary>
150+ /// <remarks>
151+ /// This requires `canUpdateOwnMetadata` permission.
152+ /// </remarks>
153+ /// <param name="name">The new name.</param>
154+ public new SetLocalNameInstruction SetName ( string name )
136155 {
137156 using var request = FFIBridge . Instance . NewRequest < SetLocalNameRequest > ( ) ;
138- var updateReq = request . request ;
139- updateReq . Name = name ;
140- var resp = request . Send ( ) ;
157+ var setReq = request . request ;
158+ setReq . LocalParticipantHandle = ( ulong ) Handle . DangerousGetHandle ( ) ;
159+ setReq . Name = name ;
160+
161+ using var response = request . Send ( ) ;
162+ FfiResponse res = response ;
163+ return new SetLocalNameInstruction ( res . SetLocalName . AsyncId ) ;
141164 }
142165
166+ /// <summary>
167+ /// Set custom attributes for the local participant.
168+ /// </summary>
169+ /// <remarks>
170+ /// This requires `canUpdateOwnMetadata` permission.
171+ /// </remarks>
172+ /// <param name="attributes">The new attributes. Existing attributes that
173+ /// are not overridden will remain unchanged.</param>
174+ public SetLocalAttributesInstruction SetAttributes ( IDictionary < string , string > attributes )
175+ {
176+ using var request = FFIBridge . Instance . NewRequest < SetLocalAttributesRequest > ( ) ;
177+ var setReq = request . request ;
178+ setReq . LocalParticipantHandle = ( ulong ) Handle . DangerousGetHandle ( ) ;
179+
180+ var newAttributes = new Dictionary < string , string > ( Attributes ) ;
181+ foreach ( var kvp in attributes )
182+ {
183+ // Override existing attributes
184+ newAttributes [ kvp . Key ] = kvp . Value ;
185+ }
186+
187+ foreach ( var kvp in newAttributes )
188+ {
189+ var entry = new AttributesEntry
190+ {
191+ Key = kvp . Key ,
192+ Value = kvp . Value
193+ } ;
194+ setReq . Attributes . Add ( entry ) ;
195+ }
196+
197+ using var response = request . Send ( ) ;
198+ FfiResponse res = response ;
199+ return new SetLocalAttributesInstruction ( res . SetLocalAttributes . AsyncId ) ;
200+ }
143201
144202 /// <summary>
145203 /// Performs RPC on another participant in the room.
@@ -514,6 +572,70 @@ internal void OnPublish(PublishTrackCallback e)
514572 FfiClient . Instance . PublishTrackReceived -= OnPublish ;
515573 }
516574 }
575+
576+ public sealed class SetLocalMetadataInstruction : YieldInstruction
577+ {
578+ private ulong _asyncId ;
579+
580+ internal SetLocalMetadataInstruction ( ulong asyncId )
581+ {
582+ _asyncId = asyncId ;
583+ FfiClient . Instance . SetLocalMetadataReceived += OnSetLocalMetadata ;
584+ }
585+
586+ internal void OnSetLocalMetadata ( SetLocalMetadataCallback e )
587+ {
588+ if ( e . AsyncId != _asyncId )
589+ return ;
590+
591+ IsError = ! string . IsNullOrEmpty ( e . Error ) ;
592+ IsDone = true ;
593+ FfiClient . Instance . SetLocalMetadataReceived -= OnSetLocalMetadata ;
594+ }
595+ }
596+
597+ public sealed class SetLocalNameInstruction : YieldInstruction
598+ {
599+ private ulong _asyncId ;
600+
601+ internal SetLocalNameInstruction ( ulong asyncId )
602+ {
603+ _asyncId = asyncId ;
604+ FfiClient . Instance . SetLocalNameReceived += OnSetLocalName ;
605+ }
606+
607+ internal void OnSetLocalName ( SetLocalNameCallback e )
608+ {
609+ if ( e . AsyncId != _asyncId )
610+ return ;
611+
612+ IsError = ! string . IsNullOrEmpty ( e . Error ) ;
613+ IsDone = true ;
614+ FfiClient . Instance . SetLocalNameReceived -= OnSetLocalName ;
615+ }
616+ }
617+
618+ public sealed class SetLocalAttributesInstruction : YieldInstruction
619+ {
620+ private ulong _asyncId ;
621+
622+ internal SetLocalAttributesInstruction ( ulong asyncId )
623+ {
624+ _asyncId = asyncId ;
625+ FfiClient . Instance . SetLocalAttributesReceived += OnSetLocalAttributes ;
626+ }
627+
628+ internal void OnSetLocalAttributes ( SetLocalAttributesCallback e )
629+ {
630+ if ( e . AsyncId != _asyncId )
631+ return ;
632+
633+ IsError = ! string . IsNullOrEmpty ( e . Error ) ;
634+ IsDone = true ;
635+ FfiClient . Instance . SetLocalAttributesReceived -= OnSetLocalAttributes ;
636+ }
637+ }
638+
517639 public sealed class UnpublishTrackInstruction : YieldInstruction
518640 {
519641 private ulong _asyncId ;
0 commit comments