| @@ -1,5 +1,4 @@ | |||||
| #define USE_THREAD | |||||
| using Discord.API; | |||||
| using Discord.API; | |||||
| using Discord.Audio; | using Discord.Audio; | ||||
| using Newtonsoft.Json; | using Newtonsoft.Json; | ||||
| using Newtonsoft.Json.Linq; | using Newtonsoft.Json.Linq; | ||||
| @@ -36,10 +35,8 @@ namespace Discord.Net.WebSockets | |||||
| private byte[] _secretKey, _encodingBuffer; | private byte[] _secretKey, _encodingBuffer; | ||||
| private ushort _sequence; | private ushort _sequence; | ||||
| private string _serverId, _channelId, _userId, _sessionId, _token, _encryptionMode; | private string _serverId, _channelId, _userId, _sessionId, _token, _encryptionMode; | ||||
| #if USE_THREAD | |||||
| private Thread _sendThread, _receiveThread; | private Thread _sendThread, _receiveThread; | ||||
| #endif | |||||
| public string CurrentServerId => _serverId; | public string CurrentServerId => _serverId; | ||||
| public string CurrentChannelId => _channelId; | public string CurrentChannelId => _channelId; | ||||
| @@ -109,9 +106,6 @@ namespace Discord.Net.WebSockets | |||||
| protected override IEnumerable<Task> GetTasks() | protected override IEnumerable<Task> GetTasks() | ||||
| { | { | ||||
| _udp = new UdpClient(new IPEndPoint(IPAddress.Any, 0)); | _udp = new UdpClient(new IPEndPoint(IPAddress.Any, 0)); | ||||
| #if !DNX451 && !__MonoCS__ | |||||
| _udp.AllowNatTraversal(true); | |||||
| #endif | |||||
| VoiceLoginCommand msg = new VoiceLoginCommand(); | VoiceLoginCommand msg = new VoiceLoginCommand(); | ||||
| msg.Payload.ServerId = _serverId; | msg.Payload.ServerId = _serverId; | ||||
| @@ -123,16 +117,11 @@ namespace Discord.Net.WebSockets | |||||
| List<Task> tasks = new List<Task>(); | List<Task> tasks = new List<Task>(); | ||||
| if ((_client.Config.VoiceMode & DiscordVoiceMode.Outgoing) != 0) | if ((_client.Config.VoiceMode & DiscordVoiceMode.Outgoing) != 0) | ||||
| { | { | ||||
| #if USE_THREAD | |||||
| _sendThread = new Thread(new ThreadStart(() => SendVoiceAsync(_cancelToken))); | _sendThread = new Thread(new ThreadStart(() => SendVoiceAsync(_cancelToken))); | ||||
| _sendThread.IsBackground = true; | _sendThread.IsBackground = true; | ||||
| _sendThread.Start(); | _sendThread.Start(); | ||||
| #else | |||||
| tasks.Add(SendVoiceAsync()); | |||||
| #endif | |||||
| } | } | ||||
| #if USE_THREAD | |||||
| //This thread is required to establish a connection even if we're outgoing only | //This thread is required to establish a connection even if we're outgoing only | ||||
| if ((_client.Config.VoiceMode & DiscordVoiceMode.Incoming) != 0) | if ((_client.Config.VoiceMode & DiscordVoiceMode.Incoming) != 0) | ||||
| { | { | ||||
| @@ -142,9 +131,6 @@ namespace Discord.Net.WebSockets | |||||
| } | } | ||||
| else //Dont make an OS thread if we only want to capture one packet... | else //Dont make an OS thread if we only want to capture one packet... | ||||
| tasks.Add(Task.Run(() => ReceiveVoiceAsync(_cancelToken))); | tasks.Add(Task.Run(() => ReceiveVoiceAsync(_cancelToken))); | ||||
| #else | |||||
| tasks.Add(ReceiveVoiceAsync()); | |||||
| #endif | |||||
| tasks.Add(WatcherAsync()); | tasks.Add(WatcherAsync()); | ||||
| if (tasks.Count > 0) | if (tasks.Count > 0) | ||||
| @@ -162,14 +148,12 @@ namespace Discord.Net.WebSockets | |||||
| } | } | ||||
| protected override Task Cleanup() | protected override Task Cleanup() | ||||
| { | { | ||||
| #if USE_THREAD | |||||
| if (_sendThread != null) | if (_sendThread != null) | ||||
| _sendThread.Join(); | _sendThread.Join(); | ||||
| if (_receiveThread != null) | if (_receiveThread != null) | ||||
| _receiveThread.Join(); | _receiveThread.Join(); | ||||
| _sendThread = null; | _sendThread = null; | ||||
| _receiveThread = null; | _receiveThread = null; | ||||
| #endif | |||||
| OpusDecoder decoder; | OpusDecoder decoder; | ||||
| foreach (var pair in _decoders) | foreach (var pair in _decoders) | ||||
| @@ -189,18 +173,9 @@ namespace Discord.Net.WebSockets | |||||
| return base.Cleanup(); | return base.Cleanup(); | ||||
| } | } | ||||
| #if USE_THREAD | |||||
| private void ReceiveVoiceAsync(CancellationToken cancelToken) | private void ReceiveVoiceAsync(CancellationToken cancelToken) | ||||
| { | { | ||||
| #else | |||||
| private Task ReceiveVoiceAsync() | |||||
| { | |||||
| var cancelToken = _cancelToken; | |||||
| return Task.Run(async () => | |||||
| { | |||||
| #endif | |||||
| try | try | ||||
| { | { | ||||
| byte[] packet, decodingBuffer = null, nonce = null, result; | byte[] packet, decodingBuffer = null, nonce = null, result; | ||||
| @@ -215,20 +190,10 @@ namespace Discord.Net.WebSockets | |||||
| while (!cancelToken.IsCancellationRequested) | while (!cancelToken.IsCancellationRequested) | ||||
| { | { | ||||
| #if USE_THREAD | |||||
| Thread.Sleep(1); | Thread.Sleep(1); | ||||
| #elif DNXCORE50 | |||||
| await Task.Delay(1).ConfigureAwait(false); | |||||
| #endif | |||||
| #if USE_THREAD || DNXCORE50 | |||||
| if (_udp.Available > 0) | if (_udp.Available > 0) | ||||
| { | { | ||||
| packet = _udp.Receive(ref endpoint); | packet = _udp.Receive(ref endpoint); | ||||
| #else | |||||
| var msg = await _udp.ReceiveAsync().ConfigureAwait(false); | |||||
| endpoint = msg.Endpoint; | |||||
| receievedPacket = msg.Buffer; | |||||
| #endif | |||||
| packetLength = packet.Length; | packetLength = packet.Length; | ||||
| if (packetLength > 0 && endpoint.Equals(_endpoint)) | if (packetLength > 0 && endpoint.Equals(_endpoint)) | ||||
| @@ -304,40 +269,19 @@ namespace Discord.Net.WebSockets | |||||
| RaiseOnPacket(userId, _channelId, result, resultOffset, resultLength); | RaiseOnPacket(userId, _channelId, result, resultOffset, resultLength); | ||||
| } | } | ||||
| } | } | ||||
| #if USE_THREAD || DNXCORE50 | |||||
| } | } | ||||
| #endif | |||||
| } | } | ||||
| } | } | ||||
| catch (OperationCanceledException) { } | catch (OperationCanceledException) { } | ||||
| catch (InvalidOperationException) { } //Includes ObjectDisposedException | catch (InvalidOperationException) { } //Includes ObjectDisposedException | ||||
| #if !USE_THREAD | |||||
| }).ConfigureAwait(false); | |||||
| #endif | |||||
| } | } | ||||
| #if USE_THREAD | |||||
| private void SendVoiceAsync(CancellationToken cancelToken) | private void SendVoiceAsync(CancellationToken cancelToken) | ||||
| { | { | ||||
| #else | |||||
| private Task SendVoiceAsync() | |||||
| { | |||||
| var cancelToken = _cancelToken; | |||||
| return Task.Run(async () => | |||||
| { | |||||
| #endif | |||||
| try | try | ||||
| { | { | ||||
| while (!cancelToken.IsCancellationRequested && _state != (int)WebSocketState.Connected) | while (!cancelToken.IsCancellationRequested && _state != (int)WebSocketState.Connected) | ||||
| { | |||||
| #if USE_THREAD | |||||
| Thread.Sleep(1); | Thread.Sleep(1); | ||||
| #else | |||||
| await Task.Delay(1); | |||||
| #endif | |||||
| } | |||||
| if (cancelToken.IsCancellationRequested) | if (cancelToken.IsCancellationRequested) | ||||
| return; | return; | ||||
| @@ -406,11 +350,7 @@ namespace Discord.Net.WebSockets | |||||
| Buffer.BlockCopy(encodedFrame, 0, udpPacket, 12, encodedLength); | Buffer.BlockCopy(encodedFrame, 0, udpPacket, 12, encodedLength); | ||||
| rtpPacketLength = encodedLength + 12; | rtpPacketLength = encodedLength + 12; | ||||
| } | } | ||||
| #if USE_THREAD | |||||
| _udp.Send(udpPacket, rtpPacketLength); | _udp.Send(udpPacket, rtpPacketLength); | ||||
| #else | |||||
| await _udp.SendAsync(rtpPacket, rtpPacketLength).ConfigureAwait(false); | |||||
| #endif | |||||
| } | } | ||||
| timestamp = unchecked(timestamp + samplesPerFrame); | timestamp = unchecked(timestamp + samplesPerFrame); | ||||
| nextTicks += ticksPerFrame; | nextTicks += ticksPerFrame; | ||||
| @@ -420,29 +360,12 @@ namespace Discord.Net.WebSockets | |||||
| else if (ticksToNextFrame > spinLockThreshold) | else if (ticksToNextFrame > spinLockThreshold) | ||||
| { | { | ||||
| int time = (int)Math.Ceiling((ticksToNextFrame - spinLockThreshold) / ticksPerMillisecond); | int time = (int)Math.Ceiling((ticksToNextFrame - spinLockThreshold) / ticksPerMillisecond); | ||||
| #if USE_THREAD | |||||
| Thread.Sleep(1); | Thread.Sleep(1); | ||||
| #else | |||||
| await Task.Delay(1).ConfigureAwait(false); | |||||
| #endif | |||||
| } | } | ||||
| //Don't spinlock if we're not actually sending audio (or buffer underrunning) | |||||
| /*else if (_sendQueue.Count == 0) | |||||
| { | |||||
| int time = (int)Math.Ceiling(ticksToNextFrame / ticksPerMillisecond); | |||||
| #if USE_THREAD | |||||
| Thread.Sleep(1); | |||||
| #else | |||||
| await Task.Delay(1).ConfigureAwait(false); | |||||
| #endif | |||||
| }*/ | |||||
| } | } | ||||
| } | } | ||||
| catch (OperationCanceledException) { } | catch (OperationCanceledException) { } | ||||
| catch (InvalidOperationException) { } //Includes ObjectDisposedException | catch (InvalidOperationException) { } //Includes ObjectDisposedException | ||||
| #if !USE_THREAD | |||||
| }).ConfigureAwait(false); | |||||
| #endif | |||||
| } | } | ||||
| //Closes the UDP socket when _disconnectToken is triggered, since UDPClient doesn't allow passing a canceltoken | //Closes the UDP socket when _disconnectToken is triggered, since UDPClient doesn't allow passing a canceltoken | ||||
| private Task WatcherAsync() | private Task WatcherAsync() | ||||