Browse Source

Fixed Audio compile errors

tags/docs-0.9
RogueException 9 years ago
parent
commit
38e2501e61
6 changed files with 89 additions and 87 deletions
  1. +1
    -1
      src/Discord.Net.Audio/AudioExtensions.cs
  2. +7
    -7
      src/Discord.Net.Audio/AudioService.cs
  3. +42
    -38
      src/Discord.Net.Audio/DiscordAudioClient.cs
  4. +35
    -39
      src/Discord.Net.Audio/Net/WebSockets/VoiceWebSocket.cs
  5. +3
    -1
      src/Discord.Net/DiscordClient.cs
  6. +1
    -1
      src/Discord.Net/Net/WebSockets/WebSocket.cs

+ 1
- 1
src/Discord.Net.Audio/AudioExtensions.cs View File

@@ -3,6 +3,6 @@
public static class AudioExtensions public static class AudioExtensions
{ {
public static AudioService Audio(this DiscordClient client, bool required = true) public static AudioService Audio(this DiscordClient client, bool required = true)
=> client.GetService<AudioService>(required);
=> client.Services.Get<AudioService>(required);
} }
} }

+ 7
- 7
src/Discord.Net.Audio/AudioService.cs View File

@@ -11,7 +11,7 @@ namespace Discord.Audio
public readonly ulong ServerId; public readonly ulong ServerId;


public VoiceDisconnectedEventArgs(ulong serverId, DisconnectedEventArgs e) public VoiceDisconnectedEventArgs(ulong serverId, DisconnectedEventArgs e)
: base(e.WasUnexpected, e.Error)
: base(e.WasUnexpected, e.Exception)
{ {
ServerId = serverId; ServerId = serverId;
} }
@@ -45,8 +45,8 @@ namespace Discord.Audio
} }


public class AudioService : IService public class AudioService : IService
{
private DiscordAudioClient _defaultClient;
{
private DiscordAudioClient _defaultClient;
private ConcurrentDictionary<ulong, DiscordAudioClient> _voiceClients; private ConcurrentDictionary<ulong, DiscordAudioClient> _voiceClients;
private ConcurrentDictionary<User, bool> _talkingUsers; private ConcurrentDictionary<User, bool> _talkingUsers;
private int _nextClientId; private int _nextClientId;
@@ -94,8 +94,8 @@ namespace Discord.Audio
_voiceClients = new ConcurrentDictionary<ulong, DiscordAudioClient>(); _voiceClients = new ConcurrentDictionary<ulong, DiscordAudioClient>();
else else
{ {
var logger = Client.Log().CreateLogger("Voice");
_defaultClient = new DiscordAudioClient(this, 0, logger, _client.WebSocket);
var logger = Client.Log.CreateLogger("Voice");
_defaultClient = new DiscordAudioClient(this, 0, logger, _client.GatewaySocket);
} }
_talkingUsers = new ConcurrentDictionary<User, bool>(); _talkingUsers = new ConcurrentDictionary<User, bool>();


@@ -147,7 +147,7 @@ namespace Discord.Audio
var client = _voiceClients.GetOrAdd(server.Id, _ => var client = _voiceClients.GetOrAdd(server.Id, _ =>
{ {
int id = unchecked(++_nextClientId); int id = unchecked(++_nextClientId);
var logger = Client.Log().CreateLogger($"Voice #{id}");
var logger = Client.Log.CreateLogger($"Voice #{id}");
GatewaySocket gatewaySocket = null; GatewaySocket gatewaySocket = null;
var voiceClient = new DiscordAudioClient(this, id, logger, gatewaySocket); var voiceClient = new DiscordAudioClient(this, id, logger, gatewaySocket);
voiceClient.SetServerId(server.Id); voiceClient.SetServerId(server.Id);
@@ -158,7 +158,7 @@ namespace Discord.Audio
}; };
voiceClient.VoiceSocket.IsSpeaking += (s, e) => voiceClient.VoiceSocket.IsSpeaking += (s, e) =>
{ {
var user = Client.GetUser(server, e.UserId);
var user = server.GetUser(e.UserId);
RaiseUserIsSpeakingUpdated(user, e.IsSpeaking); RaiseUserIsSpeakingUpdated(user, e.IsSpeaking);
}; };




+ 42
- 38
src/Discord.Net.Audio/DiscordAudioClient.cs View File

@@ -1,6 +1,8 @@
using Discord.API; using Discord.API;
using Discord.API.Client.GatewaySocket; using Discord.API.Client.GatewaySocket;
using Discord.Logging;
using Discord.Net.WebSockets; using Discord.Net.WebSockets;
using Newtonsoft.Json;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;


@@ -8,31 +10,33 @@ namespace Discord.Audio
{ {
public partial class DiscordAudioClient public partial class DiscordAudioClient
{ {
private readonly int _id;
public int Id => _id;
private JsonSerializer _serializer;


private readonly AudioService _service;
private readonly Logger _logger;
internal AudioService Service { get; }
internal Logger Logger { get; }
public int Id { get; }
public GatewaySocket GatewaySocket { get; }
public VoiceWebSocket VoiceSocket { get; }


public GatewaySocket GatewaySocket => _gatewaySocket;
private readonly GatewaySocket _gatewaySocket;

public VoiceWebSocket VoiceSocket => _voiceSocket;
private readonly VoiceWebSocket _voiceSocket;

public string Token => _token;
private string _token;

public ulong? ServerId => _voiceSocket.ServerId;
public ulong? ChannelId => _voiceSocket.ChannelId;
public ulong? ServerId => VoiceSocket.ServerId;
public ulong? ChannelId => VoiceSocket.ChannelId;


public DiscordAudioClient(AudioService service, int id, Logger logger, GatewaySocket gatewaySocket) public DiscordAudioClient(AudioService service, int id, Logger logger, GatewaySocket gatewaySocket)
{ {
_service = service;
_id = id;
_logger = logger;
_gatewaySocket = gatewaySocket;
_voiceSocket = new VoiceWebSocket(service.Client, this, logger);
Service = service;
Id = id;
Logger = logger;

_serializer = new JsonSerializer();
_serializer.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
_serializer.Error += (s, e) =>
{
e.ErrorContext.Handled = true;
Logger.Error("Serialization Failed", e.ErrorContext.Error);
};

GatewaySocket = gatewaySocket;
VoiceSocket = new VoiceWebSocket(service.Client, this, _serializer, logger);


/*_voiceSocket.Connected += (s, e) => RaiseVoiceConnected(); /*_voiceSocket.Connected += (s, e) => RaiseVoiceConnected();
_voiceSocket.Disconnected += async (s, e) => _voiceSocket.Disconnected += async (s, e) =>
@@ -68,7 +72,7 @@ namespace Discord.Audio
_voiceSocket.ParentCancelToken = _cancelToken; _voiceSocket.ParentCancelToken = _cancelToken;
};*/ };*/


_gatewaySocket.ReceivedDispatch += async (s, e) =>
GatewaySocket.ReceivedDispatch += async (s, e) =>
{ {
try try
{ {
@@ -76,15 +80,15 @@ namespace Discord.Audio
{ {
case "VOICE_SERVER_UPDATE": case "VOICE_SERVER_UPDATE":
{ {
var data = e.Payload.ToObject<VoiceServerUpdateEvent>(_gatewaySocket.Serializer);
var data = e.Payload.ToObject<VoiceServerUpdateEvent>(_serializer);
var serverId = data.GuildId; var serverId = data.GuildId;


if (serverId == ServerId) if (serverId == ServerId)
{ {
var client = _service.Client;
_token = data.Token;
_voiceSocket.Host = "wss://" + e.Payload.Value<string>("endpoint").Split(':')[0];
await _voiceSocket.Connect().ConfigureAwait(false);
var client = Service.Client;
VoiceSocket.Token = data.Token;
VoiceSocket.Host = "wss://" + e.Payload.Value<string>("endpoint").Split(':')[0];
await VoiceSocket.Connect().ConfigureAwait(false);
} }
} }
break; break;
@@ -92,7 +96,7 @@ namespace Discord.Audio
} }
catch (Exception ex) catch (Exception ex)
{ {
_gatewaySocket.Logger.Error($"Error handling {e.Type} event", ex);
Logger.Error($"Error handling {e.Type} event", ex);
} }
}; };
} }
@@ -100,7 +104,7 @@ namespace Discord.Audio


internal void SetServerId(ulong serverId) internal void SetServerId(ulong serverId)
{ {
_voiceSocket.ServerId = serverId;
VoiceSocket.ServerId = serverId;
} }
public async Task Join(Channel channel) public async Task Join(Channel channel)
{ {
@@ -110,14 +114,14 @@ namespace Discord.Audio
throw new InvalidOperationException("Cannot join a channel on a different server than this voice client."); 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);
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);
} }
public Task Disconnect() => _voiceSocket.Disconnect();
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> /// <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> /// <param name="data">PCM frame to send. This must be a single or collection of uncompressed 48Kz monochannel 20ms PCM frames. </param>
@@ -129,7 +133,7 @@ namespace Discord.Audio
//CheckReady(checkVoice: true); //CheckReady(checkVoice: true);


if (count != 0) if (count != 0)
_voiceSocket.SendPCMFrames(data, count);
VoiceSocket.SendPCMFrames(data, count);
} }


/// <summary> Clears the PCM buffer. </summary> /// <summary> Clears the PCM buffer. </summary>
@@ -137,7 +141,7 @@ namespace Discord.Audio
{ {
//CheckReady(checkVoice: true); //CheckReady(checkVoice: true);


_voiceSocket.ClearPCMFrames();
VoiceSocket.ClearPCMFrames();
} }


/// <summary> Returns a task that completes once the voice output buffer is empty. </summary> /// <summary> Returns a task that completes once the voice output buffer is empty. </summary>
@@ -145,7 +149,7 @@ namespace Discord.Audio
{ {
//CheckReady(checkVoice: true); //CheckReady(checkVoice: true);


_voiceSocket.WaitForQueue();
VoiceSocket.WaitForQueue();
return TaskHelper.CompletedTask; return TaskHelper.CompletedTask;
} }
} }


+ 35
- 39
src/Discord.Net.Audio/Net/WebSockets/VoiceWebSocket.cs View File

@@ -4,6 +4,7 @@ using Discord.API.Client.VoiceSocket;
using Discord.Audio; using Discord.Audio;
using Discord.Audio.Opus; using Discord.Audio.Opus;
using Discord.Audio.Sodium; using Discord.Audio.Sodium;
using Discord.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System; using System;
@@ -24,35 +25,33 @@ namespace Discord.Net.WebSockets
private const int MaxOpusSize = 4000; private const int MaxOpusSize = 4000;
private const string EncryptedMode = "xsalsa20_poly1305"; private const string EncryptedMode = "xsalsa20_poly1305";
private const string UnencryptedMode = "plain"; private const string UnencryptedMode = "plain";

//private readonly Random _rand;
private readonly int _targetAudioBufferLength; private readonly int _targetAudioBufferLength;
private readonly ConcurrentDictionary<uint, OpusDecoder> _decoders; private readonly ConcurrentDictionary<uint, OpusDecoder> _decoders;
private readonly DiscordAudioClient _audioClient; private readonly DiscordAudioClient _audioClient;
private readonly AudioServiceConfig _config; private readonly AudioServiceConfig _config;
private OpusEncoder _encoder;
private Thread _sendThread, _receiveThread;
private VoiceBuffer _sendBuffer;
private OpusEncoder _encoder;
private uint _ssrc; private uint _ssrc;
private ConcurrentDictionary<uint, ulong> _ssrcMapping; private ConcurrentDictionary<uint, ulong> _ssrcMapping;

private VoiceBuffer _sendBuffer;
private UdpClient _udp; private UdpClient _udp;
private IPEndPoint _endpoint; private IPEndPoint _endpoint;
private bool _isEncrypted; private bool _isEncrypted;
private byte[] _secretKey, _encodingBuffer; private byte[] _secretKey, _encodingBuffer;
private ushort _sequence; private ushort _sequence;
private ulong? _serverId, _channelId;
private string _encryptionMode; private string _encryptionMode;
private int _ping;
private Thread _sendThread, _receiveThread;
public ulong? ServerId { get { return _serverId; } internal set { _serverId = value; } }
public ulong? ChannelId { get { return _channelId; } internal set { _channelId = value; } }
public int Ping => _ping;
private int _ping;
public string Token { get; internal set; }
public ulong? ServerId { get; internal set; }
public ulong? ChannelId { get; internal set; }
public int Ping => _ping;
internal VoiceBuffer OutputBuffer => _sendBuffer; internal VoiceBuffer OutputBuffer => _sendBuffer;


public VoiceWebSocket(DiscordClient client, DiscordAudioClient audioClient, Logger logger)
: base(client, logger)
public VoiceWebSocket(DiscordClient client, DiscordAudioClient audioClient, JsonSerializer serializer, Logger logger)
: base(client, serializer, logger)
{ {
_audioClient = audioClient; _audioClient = audioClient;
_config = client.Audio().Config; _config = client.Audio().Config;
@@ -84,7 +83,7 @@ namespace Discord.Net.WebSockets
catch (OperationCanceledException) { throw; } catch (OperationCanceledException) { throw; }
catch (Exception ex) catch (Exception ex)
{ {
_logger.Error("Reconnect failed", ex);
Logger.Error("Reconnect failed", ex);
//Net is down? We can keep trying to reconnect until the user runs Disconnect() //Net is down? We can keep trying to reconnect until the user runs Disconnect()
await Task.Delay(_client.Config.FailedReconnectDelay, cancelToken).ConfigureAwait(false); await Task.Delay(_client.Config.FailedReconnectDelay, cancelToken).ConfigureAwait(false);
} }
@@ -101,14 +100,14 @@ namespace Discord.Net.WebSockets
List<Task> tasks = new List<Task>(); List<Task> tasks = new List<Task>();
if ((_config.Mode & AudioMode.Outgoing) != 0) if ((_config.Mode & AudioMode.Outgoing) != 0)
{ {
_sendThread = new Thread(new ThreadStart(() => SendVoiceAsync(_cancelToken)));
_sendThread = new Thread(new ThreadStart(() => SendVoiceAsync(CancelToken)));
_sendThread.IsBackground = true; _sendThread.IsBackground = true;
_sendThread.Start(); _sendThread.Start();
} }
if ((_config.Mode & AudioMode.Incoming) != 0) if ((_config.Mode & AudioMode.Incoming) != 0)
{ {
_receiveThread = new Thread(new ThreadStart(() => ReceiveVoiceAsync(_cancelToken)));
_receiveThread.IsBackground = true;
_receiveThread = new Thread(new ThreadStart(() => ReceiveVoiceAsync(CancelToken)));
_receiveThread.IsBackground = true;
_receiveThread.Start(); _receiveThread.Start();
} }
@@ -117,8 +116,8 @@ namespace Discord.Net.WebSockets
#if !DOTNET5_4 #if !DOTNET5_4
tasks.Add(WatcherAsync()); tasks.Add(WatcherAsync());
#endif #endif
tasks.AddRange(_engine.GetTasks(_cancelToken));
tasks.Add(HeartbeatAsync(_cancelToken));
tasks.AddRange(_engine.GetTasks(CancelToken));
tasks.Add(HeartbeatAsync(CancelToken));
await _taskManager.Start(tasks, _cancelTokenSource).ConfigureAwait(false); await _taskManager.Start(tasks, _cancelTokenSource).ConfigureAwait(false);
} }
protected override Task Cleanup() protected override Task Cleanup()
@@ -179,7 +178,7 @@ namespace Discord.Net.WebSockets


if (packetLength > 0 && endpoint.Equals(_endpoint)) if (packetLength > 0 && endpoint.Equals(_endpoint))
{ {
if (_state != ConnectionState.Connected)
if (State != ConnectionState.Connected)
{ {
if (packetLength != 70) if (packetLength != 70)
return; return;
@@ -235,7 +234,7 @@ namespace Discord.Net.WebSockets


ulong userId; ulong userId;
if (_ssrcMapping.TryGetValue(ssrc, out userId)) if (_ssrcMapping.TryGetValue(ssrc, out userId))
RaiseOnPacket(userId, _channelId.Value, result, resultOffset, resultLength);
RaiseOnPacket(userId, ChannelId.Value, result, resultOffset, resultLength);
} }
} }
} }
@@ -249,7 +248,7 @@ namespace Discord.Net.WebSockets
{ {
try try
{ {
while (!cancelToken.IsCancellationRequested && _state != ConnectionState.Connected)
while (!cancelToken.IsCancellationRequested && State != ConnectionState.Connected)
Thread.Sleep(1); Thread.Sleep(1);


if (cancelToken.IsCancellationRequested) if (cancelToken.IsCancellationRequested)
@@ -353,7 +352,7 @@ namespace Discord.Net.WebSockets
} }
catch (SocketException ex) catch (SocketException ex)
{ {
_logger.Error("Failed to send UDP packet.", ex);
Logger.Error("Failed to send UDP packet.", ex);
} }
hasFrame = false; hasFrame = false;
} }
@@ -385,11 +384,7 @@ namespace Discord.Net.WebSockets
#if !DOTNET5_4 #if !DOTNET5_4
//Closes the UDP socket when _disconnectToken is triggered, since UDPClient doesn't allow passing a canceltoken //Closes the UDP socket when _disconnectToken is triggered, since UDPClient doesn't allow passing a canceltoken
private Task WatcherAsync() private Task WatcherAsync()
{
var cancelToken = _cancelToken;
return cancelToken.Wait()
.ContinueWith(_ => _udp.Close());
}
=> CancelToken.Wait().ContinueWith(_ => _udp.Close());
#endif #endif


protected override async Task ProcessMessage(string json) protected override async Task ProcessMessage(string json)
@@ -401,7 +396,7 @@ namespace Discord.Net.WebSockets
{ {
case OpCodes.Ready: case OpCodes.Ready:
{ {
if (_state != ConnectionState.Connected)
if (State != ConnectionState.Connected)
{ {
var payload = (msg.Payload as JToken).ToObject<ReadyEvent>(_serializer); var payload = (msg.Payload as JToken).ToObject<ReadyEvent>(_serializer);
_heartbeatInterval = payload.HeartbeatInterval; _heartbeatInterval = payload.HeartbeatInterval;
@@ -460,24 +455,23 @@ namespace Discord.Net.WebSockets
} }
break; break;
default: default:
if (_logger.Level >= LogSeverity.Warning)
_logger.Warning($"Unknown Opcode: {opCode}");
Logger.Warning($"Unknown Opcode: {opCode}");
break; break;
} }
} }


public void SendPCMFrames(byte[] data, int bytes) public void SendPCMFrames(byte[] data, int bytes)
{ {
_sendBuffer.Push(data, bytes, _cancelToken);
_sendBuffer.Push(data, bytes, CancelToken);
} }
public void ClearPCMFrames() public void ClearPCMFrames()
{ {
_sendBuffer.Clear(_cancelToken);
_sendBuffer.Clear(CancelToken);
} }


public void WaitForQueue() public void WaitForQueue()
{ {
_sendBuffer.Wait(_cancelToken);
_sendBuffer.Wait(CancelToken);
} }
public Task WaitForConnection(int timeout) public Task WaitForConnection(int timeout)
{ {
@@ -485,7 +479,7 @@ namespace Discord.Net.WebSockets
{ {
try try
{ {
if (!_connectedEvent.Wait(timeout, _cancelToken))
if (!_connectedEvent.Wait(timeout, CancelToken))
throw new TimeoutException(); throw new TimeoutException();
} }
catch (OperationCanceledException) catch (OperationCanceledException)
@@ -498,9 +492,11 @@ namespace Discord.Net.WebSockets
public override void SendHeartbeat() public override void SendHeartbeat()
=> QueueMessage(new HeartbeatCommand()); => QueueMessage(new HeartbeatCommand());
public void SendIdentify() public void SendIdentify()
=> QueueMessage(new IdentifyCommand { GuildId = _serverId.Value, UserId = _client.UserId.Value, SessionId = _client.SessionId, Token = _audioClient.Token });
=> QueueMessage(new IdentifyCommand { GuildId = ServerId.Value, UserId = _client.CurrentUser.Id,
SessionId = _client.SessionId, Token = Token });
public void SendSelectProtocol(string externalAddress, int externalPort) public void SendSelectProtocol(string externalAddress, int externalPort)
=> QueueMessage(new SelectProtocolCommand { Protocol = "udp", ExternalAddress = externalAddress, ExternalPort = externalPort, EncryptionMode = _encryptionMode });
=> QueueMessage(new SelectProtocolCommand { Protocol = "udp", ExternalAddress = externalAddress,
ExternalPort = externalPort, EncryptionMode = _encryptionMode });
public void SendSetSpeaking(bool value) public void SendSetSpeaking(bool value)
=> QueueMessage(new SetSpeakingCommand { IsSpeaking = value, Delay = 0 }); => QueueMessage(new SetSpeakingCommand { IsSpeaking = value, Delay = 0 });




+ 3
- 1
src/Discord.Net/DiscordClient.cs View File

@@ -56,6 +56,8 @@ namespace Discord
internal User PrivateUser { get; private set; } internal User PrivateUser { get; private set; }
/// <summary> Gets information about the current logged-in account. </summary> /// <summary> Gets information about the current logged-in account. </summary>
public Profile CurrentUser { get; private set; } public Profile CurrentUser { get; private set; }
/// <summary> Gets the session id for the current connection. </summary>
public string SessionId { get; private set; }
/// <summary> Gets the status of the current user. </summary> /// <summary> Gets the status of the current user. </summary>
public UserStatus Status { get; private set; } public UserStatus Status { get; private set; }
/// <summary> Gets the game this current user is reported as playing. </summary> /// <summary> Gets the game this current user is reported as playing. </summary>
@@ -448,7 +450,7 @@ namespace Discord
case "READY": //Resync case "READY": //Resync
{ {
var data = e.Payload.ToObject<ReadyEvent>(_serializer); var data = e.Payload.ToObject<ReadyEvent>(_serializer);
//SessionId = data.SessionId;
SessionId = data.SessionId;
PrivateUser = new User(this, data.User.Id, null); PrivateUser = new User(this, data.User.Id, null);
PrivateUser.Update(data.User); PrivateUser.Update(data.User);
CurrentUser.Update(data.User); CurrentUser.Update(data.User);


+ 1
- 1
src/Discord.Net/Net/WebSockets/WebSocket.cs View File

@@ -22,7 +22,7 @@ namespace Discord.Net.WebSockets
private DateTime _lastHeartbeat; private DateTime _lastHeartbeat;
/// <summary> Gets the logger used for this client. </summary> /// <summary> Gets the logger used for this client. </summary>
internal Logger Logger { get; }
protected internal Logger Logger { get; }


public CancellationToken CancelToken { get; private set; } public CancellationToken CancelToken { get; private set; }




Loading…
Cancel
Save