Started adding multiserver voice support
This commit is contained in:
@@ -59,24 +59,17 @@ namespace Discord.Audio
|
||||
public AudioClient(AudioService service, int clientId, Server server, GatewaySocket gatewaySocket, Logger logger)
|
||||
{
|
||||
Service = service;
|
||||
_serializer = service.Client.Serializer;
|
||||
Id = clientId;
|
||||
GatewaySocket = gatewaySocket;
|
||||
Logger = logger;
|
||||
OutputStream = new OutStream(this);
|
||||
|
||||
_connectionLock = new AsyncLock();
|
||||
|
||||
_serializer = new JsonSerializer();
|
||||
_serializer.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
|
||||
_serializer.Error += (s, e) =>
|
||||
{
|
||||
e.ErrorContext.Handled = true;
|
||||
Logger.Error("Serialization Failed", e.ErrorContext.Error);
|
||||
};
|
||||
_connectionLock = new AsyncLock();
|
||||
|
||||
GatewaySocket.ReceivedDispatch += OnReceivedDispatch;
|
||||
|
||||
VoiceSocket = new VoiceWebSocket(service.Client, this, _serializer, logger);
|
||||
VoiceSocket = new VoiceWebSocket(service.Client, this, logger);
|
||||
VoiceSocket.Server = server;
|
||||
|
||||
/*_voiceSocket.Connected += (s, e) => RaiseVoiceConnected();
|
||||
@@ -124,27 +117,41 @@ namespace Discord.Audio
|
||||
if (channel == VoiceSocket.Channel) return;
|
||||
if (VoiceSocket.Server == null)
|
||||
throw new InvalidOperationException("This client has been closed.");
|
||||
|
||||
using (await _connectionLock.LockAsync())
|
||||
|
||||
using (await _connectionLock.LockAsync().ConfigureAwait(false))
|
||||
{
|
||||
_cancelTokenSource = new CancellationTokenSource();
|
||||
var cancelToken = _cancelTokenSource.Token;
|
||||
VoiceSocket.ParentCancelToken = cancelToken;
|
||||
VoiceSocket.Channel = channel;
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
SendVoiceUpdate();
|
||||
VoiceSocket.WaitForConnection(cancelToken);
|
||||
VoiceSocket.WaitForConnection(_cancelTokenSource.Token);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Connect(bool connectGateway)
|
||||
{
|
||||
using (await _connectionLock.LockAsync().ConfigureAwait(false))
|
||||
{
|
||||
_cancelTokenSource = new CancellationTokenSource();
|
||||
var cancelToken = _cancelTokenSource.Token;
|
||||
VoiceSocket.ParentCancelToken = cancelToken;
|
||||
|
||||
if (connectGateway)
|
||||
{
|
||||
GatewaySocket.ParentCancelToken = cancelToken;
|
||||
await GatewaySocket.Connect().ConfigureAwait(false);
|
||||
GatewaySocket.WaitForConnection(cancelToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Disconnect()
|
||||
{
|
||||
using (await _connectionLock.LockAsync())
|
||||
using (await _connectionLock.LockAsync().ConfigureAwait(false))
|
||||
{
|
||||
Service.RemoveClient(VoiceSocket.Server, this);
|
||||
await Service.RemoveClient(VoiceSocket.Server, this).ConfigureAwait(false);
|
||||
VoiceSocket.Channel = null;
|
||||
SendVoiceUpdate();
|
||||
await VoiceSocket.Disconnect();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Discord.Net.WebSockets;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -10,7 +11,7 @@ namespace Discord.Audio
|
||||
private AudioClient _defaultClient;
|
||||
private ConcurrentDictionary<ulong, IAudioClient> _voiceClients;
|
||||
private ConcurrentDictionary<User, bool> _talkingUsers;
|
||||
//private int _nextClientId;
|
||||
private int _nextClientId;
|
||||
|
||||
internal DiscordClient Client { get; private set; }
|
||||
public AudioServiceConfig Config { get; }
|
||||
@@ -83,52 +84,71 @@ namespace Discord.Audio
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private Task<IAudioClient> CreateClient(Server server)
|
||||
private async Task<IAudioClient> CreateClient(Server server)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
/*var client = _voiceClients.GetOrAdd(server.Id, _ =>
|
||||
{
|
||||
int id = unchecked(++_nextClientId);
|
||||
var logger = Client.Log.CreateLogger($"Voice #{id}");
|
||||
var voiceClient = new DiscordAudioClient(this, id, logger, Client.GatewaySocket);
|
||||
voiceClient.SetServerId(server.Id);
|
||||
var client = _voiceClients.GetOrAdd(server.Id, _ => null); //Placeholder, so we can't have two clients connecting at once
|
||||
|
||||
voiceClient.VoiceSocket.OnPacket += (s, e) =>
|
||||
{
|
||||
RaiseOnPacket(e);
|
||||
};
|
||||
voiceClient.VoiceSocket.IsSpeaking += (s, e) =>
|
||||
{
|
||||
var user = server.GetUser(e.UserId);
|
||||
RaiseUserIsSpeakingUpdated(user, e.IsSpeaking);
|
||||
};
|
||||
if (client == null)
|
||||
{
|
||||
int id = unchecked(++_nextClientId);
|
||||
|
||||
return voiceClient;
|
||||
});
|
||||
//await client.Connect(gatewaySocket.Host, _client.Token).ConfigureAwait(false);
|
||||
return Task.FromResult(client);*/
|
||||
var gatewayLogger = Client.Log.CreateLogger($"Gateway #{id}");
|
||||
var gatewaySocket = new GatewaySocket(Client, gatewayLogger);
|
||||
await gatewaySocket.Connect().ConfigureAwait(false);
|
||||
|
||||
var voiceLogger = Client.Log.CreateLogger($"Voice #{id}");
|
||||
var voiceClient = new AudioClient(this, id, server, Client.GatewaySocket, voiceLogger);
|
||||
await voiceClient.Connect(true).ConfigureAwait(false);
|
||||
|
||||
/*voiceClient.VoiceSocket.FrameReceived += (s, e) =>
|
||||
{
|
||||
OnFrameReceieved(e);
|
||||
};
|
||||
voiceClient.VoiceSocket.UserIsSpeaking += (s, e) =>
|
||||
{
|
||||
var user = server.GetUser(e.UserId);
|
||||
OnUserIsSpeakingUpdated(user, e.IsSpeaking);
|
||||
};*/
|
||||
|
||||
//Update the placeholder only it still exists (RemoveClient wasnt called)
|
||||
if (!_voiceClients.TryUpdate(server.Id, voiceClient, null))
|
||||
{
|
||||
//If it was, cleanup
|
||||
await voiceClient.Disconnect().ConfigureAwait(false); ;
|
||||
await gatewaySocket.Disconnect().ConfigureAwait(false); ;
|
||||
}
|
||||
}
|
||||
return client;
|
||||
}
|
||||
|
||||
//TODO: This isn't threadsafe
|
||||
internal void RemoveClient(Server server, IAudioClient client)
|
||||
internal async Task RemoveClient(Server server, IAudioClient client)
|
||||
{
|
||||
if (Config.EnableMultiserver && server != null)
|
||||
_voiceClients.TryRemove(server.Id, out client);
|
||||
{
|
||||
if (_voiceClients.TryRemove(server.Id, out client))
|
||||
{
|
||||
await client.Disconnect();
|
||||
await (client as AudioClient).GatewaySocket.Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IAudioClient> Join(Channel channel)
|
||||
{
|
||||
if (channel == null) throw new ArgumentNullException(nameof(channel));
|
||||
|
||||
IAudioClient client;
|
||||
|
||||
if (!Config.EnableMultiserver)
|
||||
client = await (_defaultClient as SimpleAudioClient).Connect(channel).ConfigureAwait(false);
|
||||
{
|
||||
await (_defaultClient as SimpleAudioClient).Join(channel).ConfigureAwait(false);
|
||||
return _defaultClient;
|
||||
}
|
||||
else
|
||||
{
|
||||
client = await CreateClient(channel.Server).ConfigureAwait(false);
|
||||
var client = await CreateClient(channel.Server).ConfigureAwait(false);
|
||||
await client.Join(channel).ConfigureAwait(false);
|
||||
return client;
|
||||
}
|
||||
return client;
|
||||
}
|
||||
|
||||
public async Task Leave(Server server)
|
||||
|
||||
@@ -57,8 +57,8 @@ namespace Discord.Net.WebSockets
|
||||
internal void OnFrameReceived(ulong userId, ulong channelId, byte[] buffer, int offset, int count)
|
||||
=> FrameReceived(this, new InternalFrameEventArgs(userId, channelId, buffer, offset, count));
|
||||
|
||||
internal VoiceWebSocket(DiscordClient client, AudioClient audioClient, JsonSerializer serializer, Logger logger)
|
||||
: base(client, serializer, logger)
|
||||
internal VoiceWebSocket(DiscordClient client, AudioClient audioClient, Logger logger)
|
||||
: base(client, logger)
|
||||
{
|
||||
_audioClient = audioClient;
|
||||
_config = client.Audio().Config;
|
||||
|
||||
@@ -42,19 +42,19 @@ namespace Discord.Audio
|
||||
//Only disconnects if is current a member of this server
|
||||
public async Task Leave(VirtualClient client)
|
||||
{
|
||||
using (await _connectionLock.LockAsync())
|
||||
using (await _connectionLock.LockAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (CurrentClient == client)
|
||||
{
|
||||
CurrentClient = null;
|
||||
await Disconnect();
|
||||
await Disconnect().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal async Task<IAudioClient> Connect(Channel channel)
|
||||
internal async Task<IAudioClient> Connect(Channel channel, bool connectGateway)
|
||||
{
|
||||
using (await _connectionLock.LockAsync())
|
||||
using (await _connectionLock.LockAsync().ConfigureAwait(false))
|
||||
{
|
||||
bool changeServer = channel.Server != VoiceSocket.Server;
|
||||
if (changeServer || CurrentClient == null)
|
||||
@@ -62,8 +62,9 @@ namespace Discord.Audio
|
||||
await Disconnect().ConfigureAwait(false);
|
||||
CurrentClient = new VirtualClient(this);
|
||||
VoiceSocket.Server = channel.Server;
|
||||
await Connect(connectGateway).ConfigureAwait(false);
|
||||
}
|
||||
await Join(channel);
|
||||
await Join(channel).ConfigureAwait(false);
|
||||
return CurrentClient;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user