Readded basic voice support
This commit is contained in:
@@ -49,7 +49,7 @@ namespace Discord.Audio
|
||||
private DiscordAudioClient _defaultClient;
|
||||
private ConcurrentDictionary<ulong, DiscordAudioClient> _voiceClients;
|
||||
private ConcurrentDictionary<User, bool> _talkingUsers;
|
||||
private int _nextClientId;
|
||||
//private int _nextClientId;
|
||||
|
||||
internal DiscordClient Client => _client;
|
||||
private DiscordClient _client;
|
||||
@@ -143,13 +143,14 @@ namespace Discord.Audio
|
||||
_defaultClient.SetServerId(server.Id);
|
||||
return Task.FromResult(_defaultClient);
|
||||
}
|
||||
else
|
||||
throw new InvalidOperationException("Multiserver voice is not currently supported");
|
||||
|
||||
var client = _voiceClients.GetOrAdd(server.Id, _ =>
|
||||
/*var client = _voiceClients.GetOrAdd(server.Id, _ =>
|
||||
{
|
||||
int id = unchecked(++_nextClientId);
|
||||
var logger = Client.Log.CreateLogger($"Voice #{id}");
|
||||
GatewaySocket gatewaySocket = null;
|
||||
var voiceClient = new DiscordAudioClient(this, id, logger, gatewaySocket);
|
||||
var voiceClient = new DiscordAudioClient(this, id, logger, Client.GatewaySocket);
|
||||
voiceClient.SetServerId(server.Id);
|
||||
|
||||
voiceClient.VoiceSocket.OnPacket += (s, e) =>
|
||||
@@ -165,7 +166,7 @@ namespace Discord.Audio
|
||||
return voiceClient;
|
||||
});
|
||||
//await client.Connect(gatewaySocket.Host, _client.Token).ConfigureAwait(false);
|
||||
return Task.FromResult(client);
|
||||
return Task.FromResult(client);*/
|
||||
}
|
||||
|
||||
public async Task<DiscordAudioClient> Join(Channel channel)
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
using Discord.API;
|
||||
using Discord.API.Client.GatewaySocket;
|
||||
using Discord.API.Client.GatewaySocket;
|
||||
using Discord.Logging;
|
||||
using Discord.Net.WebSockets;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord.Audio
|
||||
{
|
||||
public partial class DiscordAudioClient
|
||||
{
|
||||
private JsonSerializer _serializer;
|
||||
{
|
||||
private readonly Semaphore _connectionLock;
|
||||
private readonly JsonSerializer _serializer;
|
||||
private CancellationTokenSource _cancelTokenSource;
|
||||
|
||||
internal AudioService Service { get; }
|
||||
internal AudioService Service { get; }
|
||||
internal Logger Logger { get; }
|
||||
public int Id { get; }
|
||||
public GatewaySocket GatewaySocket { get; }
|
||||
@@ -26,6 +28,9 @@ namespace Discord.Audio
|
||||
Service = service;
|
||||
Id = id;
|
||||
Logger = logger;
|
||||
GatewaySocket = gatewaySocket;
|
||||
|
||||
_connectionLock = new Semaphore(1, 1);
|
||||
|
||||
_serializer = new JsonSerializer();
|
||||
_serializer.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
|
||||
@@ -35,7 +40,6 @@ namespace Discord.Audio
|
||||
Logger.Error("Serialization Failed", e.ErrorContext.Error);
|
||||
};
|
||||
|
||||
GatewaySocket = gatewaySocket;
|
||||
VoiceSocket = new VoiceWebSocket(service.Client, this, _serializer, logger);
|
||||
|
||||
/*_voiceSocket.Connected += (s, e) => RaiseVoiceConnected();
|
||||
@@ -72,33 +76,7 @@ namespace Discord.Audio
|
||||
_voiceSocket.ParentCancelToken = _cancelToken;
|
||||
};*/
|
||||
|
||||
GatewaySocket.ReceivedDispatch += async (s, e) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (e.Type)
|
||||
{
|
||||
case "VOICE_SERVER_UPDATE":
|
||||
{
|
||||
var data = e.Payload.ToObject<VoiceServerUpdateEvent>(_serializer);
|
||||
var serverId = data.GuildId;
|
||||
|
||||
if (serverId == ServerId)
|
||||
{
|
||||
var client = Service.Client;
|
||||
VoiceSocket.Token = data.Token;
|
||||
VoiceSocket.Host = "wss://" + e.Payload.Value<string>("endpoint").Split(':')[0];
|
||||
await VoiceSocket.Connect().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error($"Error handling {e.Type} event", ex);
|
||||
}
|
||||
};
|
||||
GatewaySocket.ReceivedDispatch += OnReceivedDispatch;
|
||||
}
|
||||
|
||||
|
||||
@@ -106,22 +84,71 @@ namespace Discord.Audio
|
||||
{
|
||||
VoiceSocket.ServerId = serverId;
|
||||
}
|
||||
public async Task Join(Channel channel)
|
||||
public Task Join(Channel channel)
|
||||
{
|
||||
if (channel == null) throw new ArgumentNullException(nameof(channel));
|
||||
ulong? serverId = channel.Server?.Id;
|
||||
if (serverId != ServerId)
|
||||
throw new InvalidOperationException("Cannot join a channel on a different server than this voice client.");
|
||||
//CheckReady(checkVoice: true);
|
||||
//CheckReady(checkVoice: true);
|
||||
|
||||
await VoiceSocket.Disconnect().ConfigureAwait(false);
|
||||
VoiceSocket.ChannelId = channel.Id;
|
||||
GatewaySocket.SendUpdateVoice(channel.Server.Id, channel.Id,
|
||||
(Service.Config.Mode | AudioMode.Outgoing) == 0,
|
||||
(Service.Config.Mode | AudioMode.Incoming) == 0);
|
||||
await VoiceSocket.WaitForConnection(Service.Config.ConnectionTimeout).ConfigureAwait(false);
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
_connectionLock.WaitOne();
|
||||
try
|
||||
{
|
||||
await VoiceSocket.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.WaitForConnection(cancelToken);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_connectionLock.Release();
|
||||
}
|
||||
});
|
||||
}
|
||||
public Task Disconnect()
|
||||
{
|
||||
GatewaySocket.ReceivedDispatch -= OnReceivedDispatch;
|
||||
return VoiceSocket.Disconnect();
|
||||
}
|
||||
|
||||
private async void OnReceivedDispatch(object sender, WebSocketEventEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (e.Type)
|
||||
{
|
||||
case "VOICE_SERVER_UPDATE":
|
||||
{
|
||||
var data = e.Payload.ToObject<VoiceServerUpdateEvent>(_serializer);
|
||||
var serverId = data.GuildId;
|
||||
|
||||
if (serverId == ServerId)
|
||||
{
|
||||
var client = Service.Client;
|
||||
VoiceSocket.Token = data.Token;
|
||||
VoiceSocket.Host = "wss://" + e.Payload.Value<string>("endpoint").Split(':')[0];
|
||||
await VoiceSocket.Connect().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error($"Error handling {e.Type} event", ex);
|
||||
}
|
||||
}
|
||||
public Task Disconnect() => VoiceSocket.Disconnect();
|
||||
|
||||
/// <summary> Sends a PCM frame to the voice server. Will block until space frees up in the outgoing buffer. </summary>
|
||||
/// <param name="data">PCM frame to send. This must be a single or collection of uncompressed 48Kz monochannel 20ms PCM frames. </param>
|
||||
|
||||
@@ -63,10 +63,8 @@ namespace Discord.Net.WebSockets
|
||||
_sendBuffer = new VoiceBuffer((int)Math.Ceiling(_config.BufferLength / (double)_encoder.FrameLength), _encoder.FrameSize);
|
||||
}
|
||||
|
||||
public async Task Connect()
|
||||
{
|
||||
await BeginConnect().ConfigureAwait(false);
|
||||
}
|
||||
public Task Connect()
|
||||
=> BeginConnect();
|
||||
public async Task Reconnect()
|
||||
{
|
||||
try
|
||||
@@ -473,21 +471,6 @@ namespace Discord.Net.WebSockets
|
||||
{
|
||||
_sendBuffer.Wait(CancelToken);
|
||||
}
|
||||
public Task WaitForConnection(int timeout)
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_connectedEvent.Wait(timeout, CancelToken))
|
||||
throw new TimeoutException();
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
_taskManager.ThrowException();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public override void SendHeartbeat()
|
||||
=> QueueMessage(new HeartbeatCommand());
|
||||
|
||||
Reference in New Issue
Block a user