11using Discord . API . Voice ;
22using Discord . Audio . Streams ;
33using Discord . Logging ;
4- using Discord . Net ;
54using Discord . Net . Converters ;
65using Discord . WebSocket ;
76using Newtonsoft . Json ;
@@ -45,7 +44,7 @@ public StreamPair(AudioInStream reader, AudioOutStream writer)
4544 private readonly SemaphoreSlim _stateLock ;
4645 private readonly ConcurrentQueue < long > _heartbeatTimes ;
4746 private readonly ConcurrentQueue < KeyValuePair < ulong , int > > _keepaliveTimes ;
48- private readonly ConcurrentDictionary < uint , ulong > _ssrcMap ;
47+ private readonly SsrcMap _ssrcMap ;
4948 private readonly ConcurrentDictionary < ulong , StreamPair > _streams ;
5049
5150 private Task _heartbeatTask , _keepaliveTask ;
@@ -54,7 +53,7 @@ public StreamPair(AudioInStream reader, AudioOutStream writer)
5453 private string _url , _sessionId , _token ;
5554 private ulong _userId ;
5655 private uint _ssrc ;
57- private bool _isSpeaking ;
56+ private bool ? _isSpeaking ;
5857 private StopReason _stopReason ;
5958 private bool _resuming ;
6059
@@ -90,7 +89,7 @@ internal AudioClient(SocketGuild guild, int clientId, ulong channelId)
9089 _connection . Disconnected += ( exception , _ ) => _disconnectedEvent . InvokeAsync ( exception ) ;
9190 _heartbeatTimes = new ConcurrentQueue < long > ( ) ;
9291 _keepaliveTimes = new ConcurrentQueue < KeyValuePair < ulong , int > > ( ) ;
93- _ssrcMap = new ConcurrentDictionary < uint , ulong > ( ) ;
92+ _ssrcMap = new SsrcMap ( ) ;
9493 _streams = new ConcurrentDictionary < ulong , StreamPair > ( ) ;
9594
9695 _serializer = new JsonSerializer { ContractResolver = new DiscordContractResolver ( ) } ;
@@ -146,12 +145,15 @@ private async Task OnConnectingAsync()
146145
147146 //Wait for READY
148147 await _connection . WaitAsync ( ) . ConfigureAwait ( false ) ;
148+ _ssrcMap . UserSpeakingChanged += OnUserSpeakingChanged ;
149149 }
150150 private async Task OnDisconnectingAsync ( Exception ex )
151151 {
152152 await _audioLogger . DebugAsync ( "Disconnecting ApiClient" ) . ConfigureAwait ( false ) ;
153153 await ApiClient . DisconnectAsync ( ) . ConfigureAwait ( false ) ;
154154
155+ _ssrcMap . UserSpeakingChanged -= OnUserSpeakingChanged ;
156+
155157 if ( _stopReason == StopReason . Unknown && ex . InnerException is WebSocketException exception )
156158 {
157159 await _audioLogger . WarningAsync (
@@ -207,6 +209,11 @@ private async Task FinishDisconnect(Exception ex, bool wontTryReconnect)
207209 }
208210 }
209211
212+ private async void OnUserSpeakingChanged ( ulong userId , bool isSpeaking )
213+ {
214+ await _speakingUpdatedEvent . InvokeAsync ( userId , isSpeaking ) ;
215+ }
216+
210217 private async Task ClearHeartBeaters ( )
211218 {
212219 //Wait for tasks to complete
@@ -332,8 +339,7 @@ private async Task ProcessMessageAsync(VoiceOpCode opCode, object payload)
332339 throw new InvalidOperationException ( $ "Discord selected an unexpected mode: { data . Mode } ") ;
333340
334341 SecretKey = data . SecretKey ;
335- _isSpeaking = false ;
336- await ApiClient . SendSetSpeaking ( _isSpeaking ) . ConfigureAwait ( false ) ;
342+ await SetSpeakingAsync ( false ) ;
337343 _keepaliveTask = RunKeepaliveAsync ( _connection . CancelToken ) ;
338344
339345 _ = _connection . CompleteAsync ( ) ;
@@ -366,7 +372,7 @@ private async Task ProcessMessageAsync(VoiceOpCode opCode, object payload)
366372 await _audioLogger . DebugAsync ( "Received Speaking" ) . ConfigureAwait ( false ) ;
367373
368374 var data = ( payload as JToken ) . ToObject < SpeakingEvent > ( _serializer ) ;
369- _ssrcMap [ data . Ssrc ] = data . UserId ;
375+ _ssrcMap . AddClient ( data . Ssrc , data . UserId , data . Speaking ) ;
370376
371377 await _speakingUpdatedEvent . InvokeAsync ( data . UserId , data . Speaking ) ;
372378 }
@@ -468,7 +474,7 @@ private async Task ProcessPacketAsync(byte[] packet)
468474 {
469475 await _audioLogger . DebugAsync ( "Malformed Frame" ) . ConfigureAwait ( false ) ;
470476 }
471- else if ( ! _ssrcMap . TryGetValue ( ssrc , out ulong userId ) )
477+ else if ( ! _ssrcMap . TryUpdateUser ( ssrc , out ulong userId ) )
472478 {
473479 await _audioLogger . DebugAsync ( $ "Unknown SSRC { ssrc } ") . ConfigureAwait ( false ) ;
474480 }
@@ -582,7 +588,7 @@ public async Task SetSpeakingAsync(bool value)
582588 if ( _isSpeaking != value )
583589 {
584590 _isSpeaking = value ;
585- await ApiClient . SendSetSpeaking ( value ) . ConfigureAwait ( false ) ;
591+ await ApiClient . SendSetSpeaking ( value , _ssrc ) . ConfigureAwait ( false ) ;
586592 }
587593 }
588594
0 commit comments