@@ -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 | ||||
{ | { | ||||
@@ -25,6 +27,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 | ||||
{ | { | ||||
@@ -34,6 +36,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 | ||||
{ | { | ||||
if (_nonce[3]++ == byte.MaxValue) | if (_nonce[3]++ == byte.MaxValue) | ||||
@@ -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(); | |||||
} | } | ||||
} | } |