| @@ -314,6 +314,7 @@ namespace Discord.Audio | |||||
| internal void Dispose(bool disposing) | internal void Dispose(bool disposing) | ||||
| { | { | ||||
| DisconnectInternalAsync(null).GetAwaiter().GetResult(); | |||||
| if (!_isDisposed) | if (!_isDisposed) | ||||
| _isDisposed = true; | _isDisposed = true; | ||||
| ApiClient.Dispose(); | ApiClient.Dispose(); | ||||
| @@ -1,4 +1,6 @@ | |||||
| using System; | using System; | ||||
| using System.Threading; | |||||
| using System.Threading.Tasks; | |||||
| namespace Discord.Audio | namespace Discord.Audio | ||||
| { | { | ||||
| @@ -24,6 +26,10 @@ namespace Discord.Audio | |||||
| } | } | ||||
| public override void Write(byte[] buffer, int offset, int count) | public override void Write(byte[] buffer, int offset, int count) | ||||
| { | |||||
| WriteAsync(buffer, offset, count, CancellationToken.None).GetAwaiter().GetResult(); | |||||
| } | |||||
| public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) | |||||
| { | { | ||||
| //Assume threadsafe | //Assume threadsafe | ||||
| while (count > 0) | while (count > 0) | ||||
| @@ -37,7 +43,7 @@ namespace Discord.Audio | |||||
| _partialFramePos = 0; | _partialFramePos = 0; | ||||
| int encFrameSize = _encoder.EncodeFrame(_partialFrameBuffer, 0, _frameSize, _buffer, 0); | int encFrameSize = _encoder.EncodeFrame(_partialFrameBuffer, 0, _frameSize, _buffer, 0); | ||||
| base.Write(_buffer, 0, encFrameSize); | |||||
| await base.WriteAsync(_buffer, 0, encFrameSize, cancellationToken).ConfigureAwait(false); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -48,6 +54,22 @@ namespace Discord.Audio | |||||
| } | } | ||||
| } | } | ||||
| public override void Flush() | |||||
| { | |||||
| FlushAsync(CancellationToken.None).GetAwaiter().GetResult(); | |||||
| } | |||||
| public override async Task FlushAsync(CancellationToken cancellationToken) | |||||
| { | |||||
| try | |||||
| { | |||||
| int encFrameSize = _encoder.EncodeFrame(_partialFrameBuffer, 0, _partialFramePos, _buffer, 0); | |||||
| base.Write(_buffer, 0, encFrameSize); | |||||
| } | |||||
| catch (Exception) { } //Incomplete frame | |||||
| _partialFramePos = 0; | |||||
| await base.FlushAsync(cancellationToken).ConfigureAwait(false); | |||||
| } | |||||
| protected override void Dispose(bool disposing) | protected override void Dispose(bool disposing) | ||||
| { | { | ||||
| base.Dispose(disposing); | base.Dispose(disposing); | ||||
| @@ -1,5 +1,7 @@ | |||||
| using System; | using System; | ||||
| using System.IO; | using System.IO; | ||||
| using System.Threading; | |||||
| using System.Threading.Tasks; | |||||
| namespace Discord.Audio | namespace Discord.Audio | ||||
| { | { | ||||
| @@ -33,6 +35,10 @@ namespace Discord.Audio | |||||
| } | } | ||||
| public override void Write(byte[] buffer, int offset, int count) | public override void Write(byte[] buffer, int offset, int count) | ||||
| { | |||||
| WriteAsync(buffer, offset, count, CancellationToken.None).GetAwaiter().GetResult(); | |||||
| } | |||||
| public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) | |||||
| { | { | ||||
| unchecked | unchecked | ||||
| { | { | ||||
| @@ -48,10 +54,17 @@ namespace Discord.Audio | |||||
| count = SecretBox.Encrypt(buffer, offset, count, _buffer, 12, _nonce, _secretKey); | count = SecretBox.Encrypt(buffer, offset, count, _buffer, 12, _nonce, _secretKey); | ||||
| Buffer.BlockCopy(_nonce, 0, _buffer, 0, 12); //Copy the RTP header from nonce to buffer | Buffer.BlockCopy(_nonce, 0, _buffer, 0, 12); //Copy the RTP header from nonce to buffer | ||||
| _target.SendAsync(_buffer, count + 12).GetAwaiter().GetResult(); | |||||
| await _target.SendAsync(_buffer, count + 12).ConfigureAwait(false); | |||||
| } | } | ||||
| public override void Flush() { } | |||||
| public override void Flush() | |||||
| { | |||||
| FlushAsync(CancellationToken.None).GetAwaiter().GetResult(); | |||||
| } | |||||
| public override async Task FlushAsync(CancellationToken cancellationToken) | |||||
| { | |||||
| await _target.FlushAsync().ConfigureAwait(false); | |||||
| } | |||||
| public override long Length { get { throw new NotSupportedException(); } } | public override long Length { get { throw new NotSupportedException(); } } | ||||
| public override long Position | public override long Position | ||||
| @@ -65,6 +65,16 @@ namespace Discord.Audio | |||||
| return Task.Delay(0); | return Task.Delay(0); | ||||
| } | } | ||||
| public async Task FlushAsync() | |||||
| { | |||||
| while (true) | |||||
| { | |||||
| if (_queue.Count == 0) | |||||
| return; | |||||
| await Task.Delay(250).ConfigureAwait(false); | |||||
| } | |||||
| } | |||||
| protected void Dispose(bool disposing) | protected void Dispose(bool disposing) | ||||
| { | { | ||||
| if (disposing) | if (disposing) | ||||
| @@ -12,5 +12,8 @@ namespace Discord.Audio | |||||
| public Task SendAsync(byte[] buffer, int count) | public Task SendAsync(byte[] buffer, int count) | ||||
| => _client.SendAsync(buffer, count); | => _client.SendAsync(buffer, count); | ||||
| public Task FlushAsync() | |||||
| => Task.Delay(0); | |||||
| } | } | ||||
| } | } | ||||
| @@ -5,5 +5,6 @@ namespace Discord.Audio | |||||
| internal interface IAudioTarget | internal interface IAudioTarget | ||||
| { | { | ||||
| Task SendAsync(byte[] buffer, int count); | Task SendAsync(byte[] buffer, int count); | ||||
| Task FlushAsync(); | |||||
| } | } | ||||
| } | } | ||||