From e42c7d290fcd50a1f75d0093650368280ca92ef1 Mon Sep 17 00:00:00 2001 From: RogueException Date: Wed, 30 Dec 2015 05:51:39 -0400 Subject: [PATCH] Fixed several voice bugs --- src/Discord.Net.Audio/AudioService.cs | 8 +-- src/Discord.Net.Audio/DiscordAudioClient.cs | 55 ++++++++++++------- .../Net/WebSockets/VoiceWebSocket.cs | 14 +++-- .../GatewaySocket/Commands/UpdateVoice.cs | 8 +-- .../Net/WebSockets/GatewaySocket.cs | 2 +- 5 files changed, 53 insertions(+), 34 deletions(-) diff --git a/src/Discord.Net.Audio/AudioService.cs b/src/Discord.Net.Audio/AudioService.cs index 1f41fb3e3..b9f1241be 100644 --- a/src/Discord.Net.Audio/AudioService.cs +++ b/src/Discord.Net.Audio/AudioService.cs @@ -136,12 +136,12 @@ namespace Discord.Audio else return null; } - private Task CreateClient(Server server) + private async Task CreateClient(Server server) { if (!Config.EnableMultiserver) { - _defaultClient.SetServerId(server.Id); - return Task.FromResult(_defaultClient); + await _defaultClient.SetServer(server.Id); + return _defaultClient; } else throw new InvalidOperationException("Multiserver voice is not currently supported"); @@ -175,7 +175,7 @@ namespace Discord.Audio //CheckReady(true); var client = await CreateClient(channel.Server).ConfigureAwait(false); - await client.Join(channel).ConfigureAwait(false); + await client.JoinChannel(channel).ConfigureAwait(false); return client; } diff --git a/src/Discord.Net.Audio/DiscordAudioClient.cs b/src/Discord.Net.Audio/DiscordAudioClient.cs index 2665dc087..a3cde89e3 100644 --- a/src/Discord.Net.Audio/DiscordAudioClient.cs +++ b/src/Discord.Net.Audio/DiscordAudioClient.cs @@ -22,6 +22,7 @@ namespace Discord.Audio public ulong? ServerId => VoiceSocket.ServerId; public ulong? ChannelId => VoiceSocket.ChannelId; + public ConnectionState State => VoiceSocket.State; public DiscordAudioClient(AudioService service, int id, Logger logger, GatewaySocket gatewaySocket) { @@ -76,51 +77,57 @@ namespace Discord.Audio _voiceSocket.ParentCancelToken = _cancelToken; };*/ - GatewaySocket.ReceivedDispatch += OnReceivedDispatch; - } + } - internal void SetServerId(ulong serverId) + internal async Task SetServer(ulong serverId) { - VoiceSocket.ServerId = serverId; + if (serverId != VoiceSocket.ServerId) + { + await Disconnect().ConfigureAwait(false); + VoiceSocket.ServerId = serverId; + VoiceSocket.ChannelId = null; + SendVoiceUpdate(); + } } - public Task Join(Channel channel) + public Task JoinChannel(Channel channel) { if (channel == null) throw new ArgumentNullException(nameof(channel)); - ulong? serverId = channel.Server?.Id; - if (serverId != ServerId) + var serverId = channel.Server?.Id; + var channelId = channel.Id; + if (serverId != ServerId) throw new InvalidOperationException("Cannot join a channel on a different server than this voice client."); + if (channelId == VoiceSocket.ChannelId) + return TaskHelper.CompletedTask; //CheckReady(checkVoice: true); - + return Task.Run(async () => { _connectionLock.WaitOne(); + GatewaySocket.ReceivedDispatch += OnReceivedDispatch; try { - await VoiceSocket.Disconnect().ConfigureAwait(false); + if (State != ConnectionState.Disconnected) + await Disconnect().ConfigureAwait(false); _cancelTokenSource = new CancellationTokenSource(); var cancelToken = _cancelTokenSource.Token; VoiceSocket.ParentCancelToken = cancelToken; - VoiceSocket.ChannelId = channel.Id; - GatewaySocket.SendUpdateVoice(channel.Server.Id, channel.Id, - (Service.Config.Mode | AudioMode.Outgoing) == 0, - (Service.Config.Mode | AudioMode.Incoming) == 0); + VoiceSocket.ChannelId = channelId; + SendVoiceUpdate(); VoiceSocket.WaitForConnection(cancelToken); } finally { + GatewaySocket.ReceivedDispatch -= OnReceivedDispatch; _connectionLock.Release(); } }); } public Task Disconnect() - { - GatewaySocket.ReceivedDispatch -= OnReceivedDispatch; - return VoiceSocket.Disconnect(); - } + => VoiceSocket.Disconnect(); private async void OnReceivedDispatch(object sender, WebSocketEventEventArgs e) { @@ -172,12 +179,22 @@ namespace Discord.Audio } /// Returns a task that completes once the voice output buffer is empty. - public Task Wait() + public void Wait() { //CheckReady(checkVoice: true); VoiceSocket.WaitForQueue(); - return TaskHelper.CompletedTask; } + + private void SendVoiceUpdate() + { + var serverId = VoiceSocket.ServerId; + if (serverId != null) + { + GatewaySocket.SendUpdateVoice(serverId, VoiceSocket.ChannelId, + (Service.Config.Mode | AudioMode.Outgoing) == 0, + (Service.Config.Mode | AudioMode.Incoming) == 0); + } + } } } diff --git a/src/Discord.Net.Audio/Net/WebSockets/VoiceWebSocket.cs b/src/Discord.Net.Audio/Net/WebSockets/VoiceWebSocket.cs index e4f40f7ff..7cfa45bfc 100644 --- a/src/Discord.Net.Audio/Net/WebSockets/VoiceWebSocket.cs +++ b/src/Discord.Net.Audio/Net/WebSockets/VoiceWebSocket.cs @@ -101,13 +101,15 @@ namespace Discord.Net.WebSockets _sendThread = new Thread(new ThreadStart(() => SendVoiceAsync(CancelToken))); _sendThread.IsBackground = true; _sendThread.Start(); - } - if ((_config.Mode & AudioMode.Incoming) != 0) - { - _receiveThread = new Thread(new ThreadStart(() => ReceiveVoiceAsync(CancelToken))); - _receiveThread.IsBackground = true; - _receiveThread.Start(); } + /*if ((_config.Mode & AudioMode.Incoming) != 0) + {*/ + _receiveThread = new Thread(new ThreadStart(() => ReceiveVoiceAsync(CancelToken))); + _receiveThread.IsBackground = true; + _receiveThread.Start(); + /*} + else + tasks.Add(Task.Run(() => ReceiveVoiceAsync(CancelToken)));*/ SendIdentify(); diff --git a/src/Discord.Net/API/Client/GatewaySocket/Commands/UpdateVoice.cs b/src/Discord.Net/API/Client/GatewaySocket/Commands/UpdateVoice.cs index 378afbed3..4eced5dcf 100644 --- a/src/Discord.Net/API/Client/GatewaySocket/Commands/UpdateVoice.cs +++ b/src/Discord.Net/API/Client/GatewaySocket/Commands/UpdateVoice.cs @@ -10,10 +10,10 @@ namespace Discord.API.Client.GatewaySocket object IWebSocketMessage.Payload => this; bool IWebSocketMessage.IsPrivate => false; - [JsonProperty("guild_id"), JsonConverter(typeof(LongStringConverter))] - public ulong GuildId { get; set; } - [JsonProperty("channel_id"), JsonConverter(typeof(LongStringConverter))] - public ulong ChannelId { get; set; } + [JsonProperty("guild_id"), JsonConverter(typeof(NullableLongStringConverter))] + public ulong? GuildId { get; set; } + [JsonProperty("channel_id"), JsonConverter(typeof(NullableLongStringConverter))] + public ulong? ChannelId { get; set; } [JsonProperty("self_mute")] public bool IsSelfMuted { get; set; } [JsonProperty("self_deaf")] diff --git a/src/Discord.Net/Net/WebSockets/GatewaySocket.cs b/src/Discord.Net/Net/WebSockets/GatewaySocket.cs index 86495a516..06048d59b 100644 --- a/src/Discord.Net/Net/WebSockets/GatewaySocket.cs +++ b/src/Discord.Net/Net/WebSockets/GatewaySocket.cs @@ -173,7 +173,7 @@ namespace Discord.Net.WebSockets IdleSince = idleSince, Game = gameName != null ? new UpdateStatusCommand.GameInfo { Name = gameName } : null }); - public void SendUpdateVoice(ulong serverId, ulong channelId, bool isSelfMuted, bool isSelfDeafened) + public void SendUpdateVoice(ulong? serverId, ulong? channelId, bool isSelfMuted, bool isSelfDeafened) => QueueMessage(new UpdateVoiceCommand { GuildId = serverId, ChannelId = channelId, IsSelfMuted = isSelfMuted, IsSelfDeafened = isSelfDeafened }); public void SendRequestMembers(ulong serverId, string query, int limit) => QueueMessage(new RequestMembersCommand { GuildId = serverId, Query = query, Limit = limit });