From 890904f32cf6c38abea60149b858e2bf8f63154a Mon Sep 17 00:00:00 2001 From: NovusTheory Date: Thu, 31 May 2018 16:21:57 -0500 Subject: [PATCH] Allow external VoiceChannel client API implementation (#1057) * ConnectAsync(bool external) API implemented This allows developers to handle the AudioClient externally (for example with Lavalink) * Modify ConnectAsync API and add DisconnectAsync to IAudioChannel * Update summary message on IAudioChannel.DisconnectAsync() * Review changes: - Fix `if (!external)` styling - Remove unecessary ConnectAsync overload * SocketVoiceChannel overload update * Update IAudioChannel.ConnectAsync() - Remove ConfigAction from parameters - Add SelfDeafen/SelfMute to parameters * Remove SocketVoiceChannel.ConnectAsync() default params (Inherit) --- .../Entities/Channels/IAudioChannel.cs | 7 ++++-- .../Entities/Channels/RestGroupChannel.cs | 3 ++- .../Entities/Channels/RestVoiceChannel.cs | 3 ++- .../Entities/Channels/SocketGroupChannel.cs | 3 ++- .../Entities/Channels/SocketVoiceChannel.cs | 7 ++++-- .../Entities/Guilds/SocketGuild.cs | 24 ++++++++++++------- 6 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/Discord.Net.Core/Entities/Channels/IAudioChannel.cs b/src/Discord.Net.Core/Entities/Channels/IAudioChannel.cs index afb81d92f..a152ff744 100644 --- a/src/Discord.Net.Core/Entities/Channels/IAudioChannel.cs +++ b/src/Discord.Net.Core/Entities/Channels/IAudioChannel.cs @@ -1,4 +1,4 @@ -using Discord.Audio; +using Discord.Audio; using System; using System.Threading.Tasks; @@ -7,6 +7,9 @@ namespace Discord public interface IAudioChannel : IChannel { /// Connects to this audio channel. - Task ConnectAsync(Action configAction = null); + Task ConnectAsync(bool selfDeaf = false, bool selfMute = false, bool external = false); + + /// Disconnects from this audio channel. + Task DisconnectAsync(); } } diff --git a/src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs index 367abfb4a..5ac0f2c40 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs @@ -147,7 +147,8 @@ namespace Discord.Rest => EnterTypingState(options); //IAudioChannel - Task IAudioChannel.ConnectAsync(Action configAction) { throw new NotSupportedException(); } + Task IAudioChannel.ConnectAsync(bool selfDeaf, bool selfMute, bool external) { throw new NotSupportedException(); } + Task IAudioChannel.DisconnectAsync() { throw new NotSupportedException(); } //IChannel Task IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) diff --git a/src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs index a2bead45f..13f3b5efa 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs @@ -45,7 +45,8 @@ namespace Discord.Rest private string DebuggerDisplay => $"{Name} ({Id}, Voice)"; //IAudioChannel - Task IAudioChannel.ConnectAsync(Action configAction) { throw new NotSupportedException(); } + Task IAudioChannel.ConnectAsync(bool selfDeaf, bool selfMute, bool external) { throw new NotSupportedException(); } + Task IAudioChannel.DisconnectAsync() { throw new NotSupportedException(); } //IGuildChannel Task IGuildChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs index 81b5cfbf3..125625456 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs @@ -211,7 +211,8 @@ namespace Discord.WebSocket => EnterTypingState(options); //IAudioChannel - Task IAudioChannel.ConnectAsync(Action configAction) { throw new NotSupportedException(); } + Task IAudioChannel.ConnectAsync(bool selfDeaf, bool selfMute, bool external) { throw new NotSupportedException(); } + Task IAudioChannel.DisconnectAsync() { throw new NotSupportedException(); } //IChannel Task IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs index 349621fac..f967e6e6a 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs @@ -43,11 +43,14 @@ namespace Discord.WebSocket public Task ModifyAsync(Action func, RequestOptions options = null) => ChannelHelper.ModifyAsync(this, Discord, func, options); - public async Task ConnectAsync(Action configAction = null) + public async Task ConnectAsync(bool selfDeaf, bool selfMute, bool external) { - return await Guild.ConnectAudioAsync(Id, false, false, configAction).ConfigureAwait(false); + return await Guild.ConnectAudioAsync(Id, selfDeaf, selfMute, external).ConfigureAwait(false); } + public async Task DisconnectAsync() + => await Guild.DisconnectAudioAsync(); + public override SocketGuildUser GetUser(ulong id) { var user = Guild.GetUser(id); diff --git a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs index 14263f0af..f41f61a7c 100644 --- a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs +++ b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs @@ -508,11 +508,8 @@ namespace Discord.WebSocket { return _audioClient?.GetInputStream(userId); } - internal async Task ConnectAudioAsync(ulong channelId, bool selfDeaf, bool selfMute, Action configAction) + internal async Task ConnectAudioAsync(ulong channelId, bool selfDeaf, bool selfMute, bool external) { - selfDeaf = false; - selfMute = false; - TaskCompletionSource promise; await _audioLock.WaitAsync().ConfigureAwait(false); @@ -522,6 +519,13 @@ namespace Discord.WebSocket promise = new TaskCompletionSource(); _audioConnectPromise = promise; + if (external) + { + var _ = promise.TrySetResultAsync(null); + await Discord.ApiClient.SendVoiceStateUpdateAsync(Id, channelId, selfDeaf, selfMute).ConfigureAwait(false); + return null; + } + if (_audioClient == null) { var audioClient = new AudioClient(this, Discord.GetAudioId(), channelId); @@ -529,7 +533,9 @@ namespace Discord.WebSocket { if (!promise.Task.IsCompleted) { - try { audioClient.Dispose(); } catch { } + try + { audioClient.Dispose(); } + catch { } _audioClient = null; if (ex != null) await promise.TrySetExceptionAsync(ex); @@ -543,7 +549,6 @@ namespace Discord.WebSocket var _ = promise.TrySetResultAsync(_audioClient); return Task.Delay(0); }; - configAction?.Invoke(audioClient); _audioClient = audioClient; } @@ -602,8 +607,11 @@ namespace Discord.WebSocket await _audioLock.WaitAsync().ConfigureAwait(false); try { - await RepopulateAudioStreamsAsync().ConfigureAwait(false); - await _audioClient.StartAsync(url, Discord.CurrentUser.Id, voiceState.VoiceSessionId, token).ConfigureAwait(false); + if (_audioClient != null) + { + await RepopulateAudioStreamsAsync().ConfigureAwait(false); + await _audioClient.StartAsync(url, Discord.CurrentUser.Id, voiceState.VoiceSessionId, token).ConfigureAwait(false); + } } catch (OperationCanceledException) {