diff --git a/src/Discord.Net.Rpc/API/Rpc/VoiceDevice.cs b/src/Discord.Net.Rpc/API/Rpc/VoiceDevice.cs new file mode 100644 index 000000000..4dc99d4cd --- /dev/null +++ b/src/Discord.Net.Rpc/API/Rpc/VoiceDevice.cs @@ -0,0 +1,12 @@ +using Newtonsoft.Json; + +namespace Discord.API.Rpc +{ + public class VoiceDevice + { + [JsonProperty("id")] + public string Id { get; set; } + [JsonProperty("name")] + public string Name { get; set; } + } +} diff --git a/src/Discord.Net.Rpc/API/Rpc/VoiceDeviceSettings.cs b/src/Discord.Net.Rpc/API/Rpc/VoiceDeviceSettings.cs new file mode 100644 index 000000000..9bad1dd6d --- /dev/null +++ b/src/Discord.Net.Rpc/API/Rpc/VoiceDeviceSettings.cs @@ -0,0 +1,14 @@ +using Newtonsoft.Json; + +namespace Discord.API.Rpc +{ + public class VoiceDeviceSettings + { + [JsonProperty("device_id")] + public string DeviceId { get; set; } + [JsonProperty("volume")] + public float Volume { get; set; } + [JsonProperty("available_devices")] + public VoiceDevice[] AvailableDevices { get; set; } + } +} diff --git a/src/Discord.Net.Rpc/API/Rpc/VoiceMode.cs b/src/Discord.Net.Rpc/API/Rpc/VoiceMode.cs new file mode 100644 index 000000000..f9b650fb5 --- /dev/null +++ b/src/Discord.Net.Rpc/API/Rpc/VoiceMode.cs @@ -0,0 +1,18 @@ +using Newtonsoft.Json; + +namespace Discord.API.Rpc +{ + public class VoiceMode + { + [JsonProperty("type")] + public string Type { get; set; } + [JsonProperty("auto_threshold")] + public bool AutoThreshold { get; set; } + [JsonProperty("threshold")] + public float Threshold { get; set; } + [JsonProperty("shortcut")] + public VoiceShortcut[] Shortcut { get; set; } + [JsonProperty("delay")] + public float Delay { get; set; } + } +} diff --git a/src/Discord.Net.Rpc/API/Rpc/VoiceSettings.cs b/src/Discord.Net.Rpc/API/Rpc/VoiceSettings.cs new file mode 100644 index 000000000..817c75cfe --- /dev/null +++ b/src/Discord.Net.Rpc/API/Rpc/VoiceSettings.cs @@ -0,0 +1,26 @@ +#pragma warning disable CS1591 + +using Newtonsoft.Json; + +namespace Discord.API.Rpc +{ + public class VoiceSettings + { + [JsonProperty("input")] + public VoiceDeviceSettings Input { get; set; } + [JsonProperty("output")] + public VoiceDeviceSettings Output { get; set; } + [JsonProperty("mode")] + public VoiceMode Mode { get; set; } + [JsonProperty("automatic_gain_control")] + public bool AutomaticGainControl { get; set; } + [JsonProperty("echo_cancellation")] + public bool EchoCancellation { get; set; } + [JsonProperty("noise_suppression")] + public bool NoiseSuppression { get; set; } + [JsonProperty("qos")] + public bool QualityOfService { get; set; } + [JsonProperty("silence_warning")] + public bool SilenceWarning { get; set; } + } +} diff --git a/src/Discord.Net.Rpc/API/Rpc/VoiceShortcut.cs b/src/Discord.Net.Rpc/API/Rpc/VoiceShortcut.cs new file mode 100644 index 000000000..e090071ee --- /dev/null +++ b/src/Discord.Net.Rpc/API/Rpc/VoiceShortcut.cs @@ -0,0 +1,15 @@ +using Discord.Rpc; +using Newtonsoft.Json; + +namespace Discord.API.Rpc +{ + public class VoiceShortcut + { + [JsonProperty("type")] + public VoiceShortcutType Type { get; set; } + [JsonProperty("code")] + public int Code { get; set; } + [JsonProperty("name")] + public string Name { get; set; } + } +} diff --git a/src/Discord.Net.Rpc/DiscordRpcClient.Events.cs b/src/Discord.Net.Rpc/DiscordRpcClient.Events.cs index 7e7553ffb..a966ef149 100644 --- a/src/Discord.Net.Rpc/DiscordRpcClient.Events.cs +++ b/src/Discord.Net.Rpc/DiscordRpcClient.Events.cs @@ -82,6 +82,13 @@ namespace Discord.Rpc } private readonly AsyncEvent> _speakingStoppedEvent = new AsyncEvent>(); + public event Func VoiceSettingsUpdated + { + add { _voiceSettingsUpdated.Add(value); } + remove { _voiceSettingsUpdated.Remove(value); } + } + private readonly AsyncEvent> _voiceSettingsUpdated = new AsyncEvent>(); + //Messages public event Func MessageReceived { diff --git a/src/Discord.Net.Rpc/DiscordRpcClient.cs b/src/Discord.Net.Rpc/DiscordRpcClient.cs index 4d3b92b5c..1d67cc8d0 100644 --- a/src/Discord.Net.Rpc/DiscordRpcClient.cs +++ b/src/Discord.Net.Rpc/DiscordRpcClient.cs @@ -271,6 +271,7 @@ namespace Discord.Rpc { case RpcGlobalEvent.ChannelCreated: return "CHANNEL_CREATE"; case RpcGlobalEvent.GuildCreated: return "GUILD_CREATE"; + case RpcGlobalEvent.VoiceSettingsUpdated: return "VOICE_SETTINGS_UPDATE"; default: throw new InvalidOperationException($"Unknown RPC Global Event: {rpcEvent}"); } @@ -419,6 +420,15 @@ namespace Discord.Rpc await _speakingStoppedEvent.InvokeAsync(data.UserId).ConfigureAwait(false); } break; + case "VOICE_SETTINGS_UPDATE": + { + await _rpcLogger.DebugAsync("Received Dispatch (VOICE_SETTINGS_UPDATE)").ConfigureAwait(false); + var data = (payload.Value as JToken).ToObject(_serializer); + var settings = VoiceSettings.Create(data); + + await _voiceSettingsUpdated.InvokeAsync(settings).ConfigureAwait(false); + } + break; //Messages case "MESSAGE_CREATE": diff --git a/src/Discord.Net.Rpc/Entities/VoiceDevice.cs b/src/Discord.Net.Rpc/Entities/VoiceDevice.cs new file mode 100644 index 000000000..328dd83f6 --- /dev/null +++ b/src/Discord.Net.Rpc/Entities/VoiceDevice.cs @@ -0,0 +1,20 @@ +using Model = Discord.API.Rpc.VoiceDevice; + +namespace Discord.Rpc +{ + public struct VoiceDevice + { + public string Id { get; } + public string Name { get; } + + internal VoiceDevice(string id, string name) + { + Id = id; + Name = name; + } + internal static VoiceDevice Create(Model model) + { + return new VoiceDevice(model.Id, model.Name); + } + } +} diff --git a/src/Discord.Net.Rpc/Entities/VoiceSettings.cs b/src/Discord.Net.Rpc/Entities/VoiceSettings.cs new file mode 100644 index 000000000..48e5538fd --- /dev/null +++ b/src/Discord.Net.Rpc/Entities/VoiceSettings.cs @@ -0,0 +1,60 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using Model = Discord.API.Rpc.VoiceSettings; + +namespace Discord.Rpc +{ + public class VoiceSettings + { + public string InputDeviceId { get; private set; } + public float InputVolume { get; private set; } + public IReadOnlyCollection AvailableInputDevices { get; private set; } + + public string OutputDeviceId { get; private set; } + public float OutputVolume { get; private set; } + public IReadOnlyCollection AvailableOutputDevices { get; private set; } + + public bool AutomaticGainControl { get; private set; } + public bool EchoCancellation { get; private set; } + public bool NoiseSuppression { get; private set; } + public bool QualityOfService { get; private set; } + public bool SilenceWarning { get; private set; } + + public string ActivationMode { get; private set; } + public bool AutoThreshold { get; private set; } + public float Threshold { get; private set; } + public IReadOnlyCollection Shortcuts { get; private set; } + public float Delay { get; private set; } + + internal VoiceSettings() { } + internal static VoiceSettings Create(Model model) + { + var entity = new VoiceSettings(); + entity.Update(model); + return entity; + } + internal void Update(Model model) + { + AutomaticGainControl = model.AutomaticGainControl; + EchoCancellation = model.EchoCancellation; + NoiseSuppression = model.NoiseSuppression; + QualityOfService = model.QualityOfService; + SilenceWarning = model.SilenceWarning; + + InputDeviceId = model.Input.DeviceId; + InputVolume = model.Input.Volume; + AvailableInputDevices = model.Input.AvailableDevices.Select(x => VoiceDevice.Create(x)).ToImmutableArray(); + + OutputDeviceId = model.Output.DeviceId; + OutputVolume = model.Output.Volume; + AvailableInputDevices = model.Output.AvailableDevices.Select(x => VoiceDevice.Create(x)).ToImmutableArray(); + + ActivationMode = model.Mode.Type; + AutoThreshold = model.Mode.AutoThreshold; + Threshold = model.Mode.Threshold; + Shortcuts = model.Mode.Shortcut.Select(x => VoiceShortcut.Create(x)).ToImmutableArray(); + Delay = model.Mode.Delay; + } + } +} diff --git a/src/Discord.Net.Rpc/Entities/VoiceShortcut.cs b/src/Discord.Net.Rpc/Entities/VoiceShortcut.cs new file mode 100644 index 000000000..131c06f1c --- /dev/null +++ b/src/Discord.Net.Rpc/Entities/VoiceShortcut.cs @@ -0,0 +1,22 @@ +using Model = Discord.API.Rpc.VoiceShortcut; + +namespace Discord.Rpc +{ + public struct VoiceShortcut + { + public VoiceShortcutType Type { get; } + public int Code { get; } + public string Name { get; } + + internal VoiceShortcut(VoiceShortcutType type, int code, string name) + { + Type = type; + Code = code; + Name = name; + } + internal static VoiceShortcut Create(Model model) + { + return new VoiceShortcut(model.Type, model.Code, model.Name); + } + } +} diff --git a/src/Discord.Net.Rpc/Entities/VoiceShortcutType.cs b/src/Discord.Net.Rpc/Entities/VoiceShortcutType.cs new file mode 100644 index 000000000..f3b82804e --- /dev/null +++ b/src/Discord.Net.Rpc/Entities/VoiceShortcutType.cs @@ -0,0 +1,10 @@ +namespace Discord.Rpc +{ + public enum VoiceShortcutType + { + KeyboardKey = 0, + MouseButton = 1, + KeyboardModifierKey = 2, + GamepadButton = 3 + } +} diff --git a/src/Discord.Net.Rpc/RpcGlobalEvent.cs b/src/Discord.Net.Rpc/RpcGlobalEvent.cs index 989e3f52e..673eaed5d 100644 --- a/src/Discord.Net.Rpc/RpcGlobalEvent.cs +++ b/src/Discord.Net.Rpc/RpcGlobalEvent.cs @@ -3,6 +3,7 @@ public enum RpcGlobalEvent { ChannelCreated, - GuildCreated + GuildCreated, + VoiceSettingsUpdated } }