Make them a little more consistent, and actually dispose where appropriatedispose-tweaks
| @@ -38,7 +38,7 @@ namespace Discord.Audio.Streams | |||||
| private bool _isPreloaded; | private bool _isPreloaded; | ||||
| private int _silenceFrames; | private int _silenceFrames; | ||||
| public BufferedWriteStream(AudioStream next, IAudioClient client, int bufferMillis, CancellationToken cancelToken, int maxFrameSize = 1500) | |||||
| internal BufferedWriteStream(AudioStream next, IAudioClient client, int bufferMillis, CancellationToken cancelToken, int maxFrameSize = 1500) | |||||
| : this(next, client as AudioClient, bufferMillis, cancelToken, null, maxFrameSize) { } | : this(next, client as AudioClient, bufferMillis, cancelToken, null, maxFrameSize) { } | ||||
| internal BufferedWriteStream(AudioStream next, AudioClient client, int bufferMillis, CancellationToken cancelToken, Logger logger, int maxFrameSize = 1500) | internal BufferedWriteStream(AudioStream next, AudioClient client, int bufferMillis, CancellationToken cancelToken, Logger logger, int maxFrameSize = 1500) | ||||
| { | { | ||||
| @@ -69,6 +69,13 @@ namespace Discord.Audio.Streams | |||||
| _disposeTokenSource?.Dispose(); | _disposeTokenSource?.Dispose(); | ||||
| _cancelTokenSource?.Dispose(); | _cancelTokenSource?.Dispose(); | ||||
| _queueLock?.Dispose(); | _queueLock?.Dispose(); | ||||
| try | |||||
| { | |||||
| _task.GetAwaiter().GetResult(); | |||||
| } | |||||
| catch (OperationCanceledException) | |||||
| { /* no-op */ } | |||||
| _next?.Dispose(); | |||||
| } | } | ||||
| base.Dispose(disposing); | base.Dispose(disposing); | ||||
| } | } | ||||
| @@ -23,7 +23,7 @@ namespace Discord.Audio.Streams | |||||
| public override bool CanWrite => false; | public override bool CanWrite => false; | ||||
| public override int AvailableFrames => _signal.CurrentCount; | public override int AvailableFrames => _signal.CurrentCount; | ||||
| public InputStream() | |||||
| internal InputStream() | |||||
| { | { | ||||
| _frames = new ConcurrentQueue<RTPFrame>(); | _frames = new ConcurrentQueue<RTPFrame>(); | ||||
| _signal = new SemaphoreSlim(0, MaxFrames); | _signal = new SemaphoreSlim(0, MaxFrames); | ||||
| @@ -15,7 +15,7 @@ namespace Discord.Audio.Streams | |||||
| private bool _nextMissed; | private bool _nextMissed; | ||||
| private bool _hasHeader; | private bool _hasHeader; | ||||
| public OpusDecodeStream(AudioStream next) | |||||
| internal OpusDecodeStream(AudioStream next) | |||||
| { | { | ||||
| _next = next; | _next = next; | ||||
| _buffer = new byte[OpusConverter.FrameBytes]; | _buffer = new byte[OpusConverter.FrameBytes]; | ||||
| @@ -26,7 +26,7 @@ namespace Discord.Audio.Streams | |||||
| public override void WriteHeader(ushort seq, uint timestamp, bool missed) | public override void WriteHeader(ushort seq, uint timestamp, bool missed) | ||||
| { | { | ||||
| if (_hasHeader) | if (_hasHeader) | ||||
| throw new InvalidOperationException("Header received with no payload."); | |||||
| throw new InvalidOperationException("Header received with no payload."); | |||||
| _hasHeader = true; | _hasHeader = true; | ||||
| _nextMissed = missed; | _nextMissed = missed; | ||||
| @@ -15,13 +15,22 @@ namespace Discord.Audio.Streams | |||||
| private int _partialFramePos; | private int _partialFramePos; | ||||
| private ushort _seq; | private ushort _seq; | ||||
| private uint _timestamp; | private uint _timestamp; | ||||
| public OpusEncodeStream(AudioStream next, int bitrate, AudioApplication application, int packetLoss) | |||||
| internal OpusEncodeStream(AudioStream next, int bitrate, AudioApplication application, int packetLoss) | |||||
| { | { | ||||
| _next = next; | _next = next; | ||||
| _encoder = new OpusEncoder(bitrate, application, packetLoss); | _encoder = new OpusEncoder(bitrate, application, packetLoss); | ||||
| _buffer = new byte[OpusConverter.FrameBytes]; | _buffer = new byte[OpusConverter.FrameBytes]; | ||||
| } | } | ||||
| protected override void Dispose(bool disposing) | |||||
| { | |||||
| if (disposing) | |||||
| { | |||||
| _encoder.Dispose(); | |||||
| _next.Dispose(); | |||||
| } | |||||
| base.Dispose(disposing); | |||||
| } | |||||
| public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancelToken) | public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancelToken) | ||||
| { | { | ||||
| @@ -86,13 +95,5 @@ namespace Discord.Audio.Streams | |||||
| { | { | ||||
| await _next.ClearAsync(cancelToken).ConfigureAwait(false); | await _next.ClearAsync(cancelToken).ConfigureAwait(false); | ||||
| } | } | ||||
| protected override void Dispose(bool disposing) | |||||
| { | |||||
| base.Dispose(disposing); | |||||
| if (disposing) | |||||
| _encoder.Dispose(); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -7,13 +7,13 @@ namespace Discord.Audio.Streams | |||||
| public class OutputStream : AudioOutStream | public class OutputStream : AudioOutStream | ||||
| { | { | ||||
| private readonly DiscordVoiceAPIClient _client; | private readonly DiscordVoiceAPIClient _client; | ||||
| public OutputStream(IAudioClient client) | |||||
| internal OutputStream(IAudioClient client) | |||||
| : this((client as AudioClient).ApiClient) { } | : this((client as AudioClient).ApiClient) { } | ||||
| internal OutputStream(DiscordVoiceAPIClient client) | internal OutputStream(DiscordVoiceAPIClient client) | ||||
| { | { | ||||
| _client = client; | _client = client; | ||||
| } | } | ||||
| public override void WriteHeader(ushort seq, uint timestamp, bool missed) { } //Ignore | public override void WriteHeader(ushort seq, uint timestamp, bool missed) { } //Ignore | ||||
| public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancelToken) | public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancelToken) | ||||
| { | { | ||||
| @@ -21,4 +21,4 @@ namespace Discord.Audio.Streams | |||||
| await _client.SendAsync(buffer, offset, count).ConfigureAwait(false); | await _client.SendAsync(buffer, offset, count).ConfigureAwait(false); | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| } | |||||
| @@ -14,7 +14,7 @@ namespace Discord.Audio.Streams | |||||
| public override bool CanSeek => false; | public override bool CanSeek => false; | ||||
| public override bool CanWrite => true; | public override bool CanWrite => true; | ||||
| public RTPReadStream(AudioStream next, int bufferSize = 4000) | |||||
| internal RTPReadStream(AudioStream next, int bufferSize = 4000) | |||||
| { | { | ||||
| _next = next; | _next = next; | ||||
| _buffer = new byte[bufferSize]; | _buffer = new byte[bufferSize]; | ||||
| @@ -46,7 +46,7 @@ namespace Discord.Audio.Streams | |||||
| ssrc = 0; | ssrc = 0; | ||||
| if (buffer.Length - offset < 12) | if (buffer.Length - offset < 12) | ||||
| return false; | return false; | ||||
| int version = (buffer[offset + 0] & 0b1100_0000) >> 6; | int version = (buffer[offset + 0] & 0b1100_0000) >> 6; | ||||
| if (version != 2) | if (version != 2) | ||||
| return false; | return false; | ||||
| @@ -71,8 +71,8 @@ namespace Discord.Audio.Streams | |||||
| return 12 + csics * 4; | return 12 + csics * 4; | ||||
| int extensionOffset = offset + 12 + (csics * 4); | int extensionOffset = offset + 12 + (csics * 4); | ||||
| int extensionLength = | |||||
| (buffer[extensionOffset + 2] << 8) | | |||||
| int extensionLength = | |||||
| (buffer[extensionOffset + 2] << 8) | | |||||
| (buffer[extensionOffset + 3]); | (buffer[extensionOffset + 3]); | ||||
| return extensionOffset + 4 + (extensionLength * 4); | return extensionOffset + 4 + (extensionLength * 4); | ||||
| } | } | ||||
| @@ -15,7 +15,7 @@ namespace Discord.Audio.Streams | |||||
| private uint _nextTimestamp; | private uint _nextTimestamp; | ||||
| private bool _hasHeader; | private bool _hasHeader; | ||||
| public RTPWriteStream(AudioStream next, uint ssrc, int bufferSize = 4000) | |||||
| internal RTPWriteStream(AudioStream next, uint ssrc, int bufferSize = 4000) | |||||
| { | { | ||||
| _next = next; | _next = next; | ||||
| _ssrc = ssrc; | _ssrc = ssrc; | ||||
| @@ -28,12 +28,20 @@ namespace Discord.Audio.Streams | |||||
| _header[10] = (byte)(_ssrc >> 8); | _header[10] = (byte)(_ssrc >> 8); | ||||
| _header[11] = (byte)(_ssrc >> 0); | _header[11] = (byte)(_ssrc >> 0); | ||||
| } | } | ||||
| protected override void Dispose(bool disposing) | |||||
| { | |||||
| if (disposing) | |||||
| { | |||||
| _next?.Dispose(); | |||||
| } | |||||
| base.Dispose(disposing); | |||||
| } | |||||
| public override void WriteHeader(ushort seq, uint timestamp, bool missed) | public override void WriteHeader(ushort seq, uint timestamp, bool missed) | ||||
| { | { | ||||
| if (_hasHeader) | if (_hasHeader) | ||||
| throw new InvalidOperationException("Header received with no payload"); | throw new InvalidOperationException("Header received with no payload"); | ||||
| _hasHeader = true; | _hasHeader = true; | ||||
| _nextSeq = seq; | _nextSeq = seq; | ||||
| _nextTimestamp = timestamp; | _nextTimestamp = timestamp; | ||||
| @@ -17,7 +17,7 @@ namespace Discord.Audio.Streams | |||||
| public override bool CanSeek => false; | public override bool CanSeek => false; | ||||
| public override bool CanWrite => true; | public override bool CanWrite => true; | ||||
| public SodiumDecryptStream(AudioStream next, IAudioClient client) | |||||
| internal SodiumDecryptStream(AudioStream next, IAudioClient client) | |||||
| { | { | ||||
| _next = next; | _next = next; | ||||
| _client = (AudioClient)client; | _client = (AudioClient)client; | ||||
| @@ -16,12 +16,20 @@ namespace Discord.Audio.Streams | |||||
| private ushort _nextSeq; | private ushort _nextSeq; | ||||
| private uint _nextTimestamp; | private uint _nextTimestamp; | ||||
| public SodiumEncryptStream(AudioStream next, IAudioClient client) | |||||
| internal SodiumEncryptStream(AudioStream next, IAudioClient client) | |||||
| { | { | ||||
| _next = next; | _next = next; | ||||
| _client = (AudioClient)client; | _client = (AudioClient)client; | ||||
| _nonce = new byte[24]; | _nonce = new byte[24]; | ||||
| } | } | ||||
| protected override void Dispose(bool disposing) | |||||
| { | |||||
| if (disposing) | |||||
| { | |||||
| _next?.Dispose(); | |||||
| } | |||||
| base.Dispose(disposing); | |||||
| } | |||||
| /// <exception cref="InvalidOperationException">Header received with no payload.</exception> | /// <exception cref="InvalidOperationException">Header received with no payload.</exception> | ||||
| public override void WriteHeader(ushort seq, uint timestamp, bool missed) | public override void WriteHeader(ushort seq, uint timestamp, bool missed) | ||||
| @@ -45,7 +53,7 @@ namespace Discord.Audio.Streams | |||||
| if (_client.SecretKey == null) | if (_client.SecretKey == null) | ||||
| return; | return; | ||||
| Buffer.BlockCopy(buffer, offset, _nonce, 0, 12); //Copy nonce from RTP header | Buffer.BlockCopy(buffer, offset, _nonce, 0, 12); //Copy nonce from RTP header | ||||
| count = SecretBox.Encrypt(buffer, offset + 12, count - 12, buffer, 12, _nonce, _client.SecretKey); | count = SecretBox.Encrypt(buffer, offset + 12, count - 12, buffer, 12, _nonce, _client.SecretKey); | ||||
| _next.WriteHeader(_nextSeq, _nextTimestamp, false); | _next.WriteHeader(_nextSeq, _nextTimestamp, false); | ||||