Skip to content

Commit

Permalink
Supports more events for AudioClient
Browse files Browse the repository at this point in the history
  • Loading branch information
gehongyan committed May 31, 2024
1 parent 7556a88 commit 5f233da
Show file tree
Hide file tree
Showing 5 changed files with 263 additions and 9 deletions.
64 changes: 64 additions & 0 deletions src/Kook.Net.WebSocket/Audio/AudioClient.Events.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,70 @@ public event Func<ulong, Task> PeerDisconnected

private readonly AsyncEvent<Func<ulong, Task>> _peerDisconnectedEvent = new();

public event Func<ulong, Task> HeadsetResumed
{
add => _headsetResumedEvent.Add(value);
remove => _headsetResumedEvent.Remove(value);
}

private readonly AsyncEvent<Func<ulong, Task>> _headsetResumedEvent = new();

public event Func<ulong, Task> HeadsetPaused
{
add => _headsetPausedEvent.Add(value);
remove => _headsetPausedEvent.Remove(value);
}

private readonly AsyncEvent<Func<ulong, Task>> _headsetPausedEvent = new();

public event Func<ulong, Task> ConsumerResumed
{
add => _consumerResumedEvent.Add(value);
remove => _consumerResumedEvent.Remove(value);
}

private readonly AsyncEvent<Func<ulong, Task>> _consumerResumedEvent = new();

public event Func<ulong, Task> ConsumerPaused
{
add => _consumerPausedEvent.Add(value);
remove => _consumerPausedEvent.Remove(value);
}

private readonly AsyncEvent<Func<ulong, Task>> _consumerPausedEvent = new();

public event Func<ulong, PeerPermissionInfo, Task> PeerPermissionChanged
{
add => _peerPermissionChangedEvent.Add(value);
remove => _peerPermissionChangedEvent.Remove(value);
}

private readonly AsyncEvent<Func<ulong, PeerPermissionInfo, Task>> _peerPermissionChangedEvent = new();

public event Func<ulong, int, Task> AtmospherePlayed
{
add => _atmospherePlayedEvent.Add(value);
remove => _atmospherePlayedEvent.Remove(value);
}

private readonly AsyncEvent<Func<ulong, int, Task>> _atmospherePlayedEvent = new();

public event Func<ulong, SoundtrackInfo, Task> SoundtrackStarted
{
add => _soundtrackStartedEvent.Add(value);
remove => _soundtrackStartedEvent.Remove(value);
}

private readonly AsyncEvent<Func<ulong, SoundtrackInfo, Task>> _soundtrackStartedEvent = new();

public event Func<ulong, Task> SoundtrackStopped
{
add => _soundtrackStoppedEvent.Add(value);
remove => _soundtrackStoppedEvent.Remove(value);
}

private readonly AsyncEvent<Func<ulong, Task>> _soundtrackStoppedEvent = new();

public event Func<Task> ClientDisconnected
{
add => _clientDisconnectedEvent.Add(value);
Expand Down
144 changes: 137 additions & 7 deletions src/Kook.Net.WebSocket/Audio/AudioClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,39 +212,169 @@ await ApiClient
case VoiceSocketFrameType.NewPeer:
{
if (payload is not JsonElement jsonElement
|| !jsonElement.TryGetProperty("id", out JsonElement idElement)
|| !ulong.TryParse(idElement.ToString(), out ulong id))
|| !jsonElement.TryGetProperty("id", out JsonElement peerIdElement)
|| !ulong.TryParse(peerIdElement.ToString(), out ulong peerId))
break;
await _peerConnectedEvent.InvokeAsync(id).ConfigureAwait(false);
await _peerConnectedEvent.InvokeAsync(peerId).ConfigureAwait(false);
await _audioLogger.DebugAsync("Received NewPeer").ConfigureAwait(false);
}
break;
case VoiceSocketFrameType.PeerClosed:
{
if (payload is not JsonElement jsonElement)
break;
if (!jsonElement.TryGetProperty("peerId", out JsonElement idElement)
|| !ulong.TryParse(idElement.ToString(), out ulong id))
if (!jsonElement.TryGetProperty("peerId", out JsonElement peerIdElement)
|| !ulong.TryParse(peerIdElement.ToString(), out ulong peerId))
break;
if (!jsonElement.TryGetProperty("fromId", out JsonElement fromIdElement)
|| !ulong.TryParse(fromIdElement.ToString(), out ulong fromId)
|| fromId != ChannelId)
break;

await _peerDisconnectedEvent.InvokeAsync(id).ConfigureAwait(false);
await _peerDisconnectedEvent.InvokeAsync(peerId).ConfigureAwait(false);
await _audioLogger.DebugAsync("Received PeerClosed").ConfigureAwait(false);
}
break;
case VoiceSocketFrameType.ResumeHeadset:
{
if (payload is not JsonElement jsonElement)
break;
if (!jsonElement.TryGetProperty("peerId", out JsonElement peerIdElement)
|| !ulong.TryParse(peerIdElement.ToString(), out ulong peerId))
break;

await _headsetResumedEvent.InvokeAsync(peerId).ConfigureAwait(false);
await _audioLogger.DebugAsync("Received ResumeHeadset").ConfigureAwait(false);
}
break;
case VoiceSocketFrameType.PauseHeadset:
{
if (payload is not JsonElement jsonElement)
break;
if (!jsonElement.TryGetProperty("peerId", out JsonElement peerIdElement)
|| !ulong.TryParse(peerIdElement.ToString(), out ulong peerId))
break;

await _headsetPausedEvent.InvokeAsync(peerId).ConfigureAwait(false);
await _audioLogger.DebugAsync("Received PauseHeadset").ConfigureAwait(false);
}
break;
case VoiceSocketFrameType.ConsumerResumed:
{
if (payload is not JsonElement jsonElement)
break;
if (!jsonElement.TryGetProperty("peerId", out JsonElement peerIdElement)
|| !ulong.TryParse(peerIdElement.ToString(), out ulong peerId))
break;

await _consumerResumedEvent.InvokeAsync(peerId).ConfigureAwait(false);
await _audioLogger.DebugAsync("Received ConsumerResumed").ConfigureAwait(false);
}
break;
case VoiceSocketFrameType.ConsumerPaused:
{
if (payload is not JsonElement jsonElement)
break;
if (!jsonElement.TryGetProperty("peerId", out JsonElement peerIdElement)
|| !ulong.TryParse(peerIdElement.ToString(), out ulong peerId))
break;

await _consumerPausedEvent.InvokeAsync(peerId).ConfigureAwait(false);
await _audioLogger.DebugAsync("Received ConsumerPaused").ConfigureAwait(false);
}
break;
case VoiceSocketFrameType.PeerPermissionChanged:
{
if (payload is not JsonElement jsonElement)
break;
if (!jsonElement.TryGetProperty("peerId", out JsonElement peerIdElement)
|| !ulong.TryParse(peerIdElement.ToString(), out ulong peerId))
break;
if (!jsonElement.TryGetProperty("roomId", out JsonElement roomIdElement)
|| !ulong.TryParse(roomIdElement.ToString(), out ulong roomId)
|| roomId != ChannelId)
break;
if (!jsonElement.TryGetProperty("isServerMute", out JsonElement isServerMuteElement)
|| isServerMuteElement.ValueKind is not (JsonValueKind.True or JsonValueKind.False))
break;
if (!jsonElement.TryGetProperty("isServerMuteHeadset", out JsonElement isServerMuteHeadsetElement)
|| isServerMuteHeadsetElement.ValueKind is not (JsonValueKind.True or JsonValueKind.False))
break;
if (!jsonElement.TryGetProperty("permissionFreeMic", out JsonElement permissionFreeMicElement)
|| permissionFreeMicElement.ValueKind is not (JsonValueKind.True or JsonValueKind.False))
break;
if (!jsonElement.TryGetProperty("permissionLink", out JsonElement permissionLinkElement)
|| permissionLinkElement.ValueKind is not (JsonValueKind.True or JsonValueKind.False))
break;
if (!jsonElement.TryGetProperty("permissionSay", out JsonElement permissionSayElement)
|| permissionSayElement.ValueKind is not (JsonValueKind.True or JsonValueKind.False))
break;
if (!jsonElement.TryGetProperty("permissionVoiceManage", out JsonElement permissionVoiceManageElement)
|| permissionVoiceManageElement.ValueKind is not (JsonValueKind.True or JsonValueKind.False))
break;
PeerPermissionInfo peerPermissionInfo = new()
{
MutedByGuild = isServerMuteElement.GetBoolean(),
DeafenedByGuild = isServerMuteHeadsetElement.GetBoolean(),
CanUseVoiceActivity = permissionFreeMicElement.GetBoolean(),
CanConnect = permissionLinkElement.GetBoolean(),
CanSpeak = permissionSayElement.GetBoolean(),
CanManageVoice = permissionVoiceManageElement.GetBoolean()
};

await _peerPermissionChangedEvent.InvokeAsync(peerId, peerPermissionInfo).ConfigureAwait(false);
await _audioLogger.DebugAsync("Received PeerPermissionChanged").ConfigureAwait(false);
}
break;
case VoiceSocketFrameType.Atmosphere:
{
if (payload is not JsonElement jsonElement)
break;
if (!jsonElement.TryGetProperty("peerId", out JsonElement peerIdElement)
|| !ulong.TryParse(peerIdElement.ToString(), out ulong peerId))
break;
if (!jsonElement.TryGetProperty("itemId", out JsonElement itemIdElement)
|| !int.TryParse(itemIdElement.ToString(), out int itemId))
break;

await _atmospherePlayedEvent.InvokeAsync(peerId, itemId).ConfigureAwait(false);
await _audioLogger.DebugAsync("Received Atmosphere").ConfigureAwait(false);
}
break;
case VoiceSocketFrameType.StartAccompaniment:
{
if (payload is not JsonElement jsonElement)
break;
if (!jsonElement.TryGetProperty("peerId", out JsonElement peerIdElement)
|| !ulong.TryParse(peerIdElement.ToString(), out ulong peerId))
break;
if (!jsonElement.TryGetProperty("data", out JsonElement dataElement))
break;
if (!dataElement.TryGetProperty("music_name", out JsonElement musicNameElement)
|| !dataElement.TryGetProperty("music_software", out JsonElement musicSoftwareElement)
|| !dataElement.TryGetProperty("singer", out JsonElement singerElement))
break;
SoundtrackInfo soundtrackInfo = new()
{
Software = musicSoftwareElement.ToString(),
Music = musicNameElement.ToString(),
Singer = singerElement.ToString()
};

await _soundtrackStartedEvent.InvokeAsync(peerId, soundtrackInfo).ConfigureAwait(false);
await _audioLogger.DebugAsync("Received StartAccompaniment").ConfigureAwait(false);
}
break;
case VoiceSocketFrameType.StopAccompaniment:
{
await _audioLogger.DebugAsync(type.ToString()).ConfigureAwait(false);
if (payload is not JsonElement jsonElement)
break;
if (!jsonElement.TryGetProperty("peerId", out JsonElement peerIdElement)
|| !ulong.TryParse(peerIdElement.ToString(), out ulong peerId))
break;

await _soundtrackStoppedEvent.InvokeAsync(peerId).ConfigureAwait(false);
await _audioLogger.DebugAsync("Received StopAccompaniment").ConfigureAwait(false);
}
break;
case VoiceSocketFrameType.Disconnect:
Expand Down
4 changes: 2 additions & 2 deletions src/Kook.Net.WebSocket/ConnectionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ public event Func<Exception, bool, Task> Disconnected
public CancellationToken CancellationToken { get; private set; }

internal ConnectionManager(SemaphoreSlim stateLock, Logger logger,
int connectionTimeout, Func<Task> onConnecting,
Func<Exception, Task> onDisconnecting, Action<Func<Exception, Task>> clientDisconnectHandler)
int connectionTimeout, Func<Task> onConnecting, Func<Exception, Task> onDisconnecting,
Action<Func<Exception, Task>> clientDisconnectHandler)
{
_stateLock = stateLock;
_logger = logger;
Expand Down
38 changes: 38 additions & 0 deletions src/Kook.Net.WebSocket/Entities/Audio/PeerPermissionInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
namespace Kook.Audio;

/// <summary>
/// Represents the information of a peer's permission in a voice channel.
/// </summary>
public readonly struct PeerPermissionInfo
{
/// <summary>
/// Gets whether the peer is muted by the guild.
/// </summary>
public bool MutedByGuild { get; init; }

/// <summary>
/// Gets whether the peer is deafened by the guild.
/// </summary>
public bool DeafenedByGuild { get; init; }

/// <summary>
/// Gets whether the peer can use voice activity, i.e. the peer can speak without pressing a key.
/// </summary>
public bool CanUseVoiceActivity { get; init; }

/// <summary>
/// Gets whether the peer can connect to the voice channel.
/// </summary>
public bool CanConnect { get; init; }

/// <summary>
/// Gets whether the peer can speak in the voice channel.
/// </summary>
public bool CanSpeak { get; init; }

/// <summary>
/// Gets whether the peer can manage the voice channel.
/// </summary>
public bool CanManageVoice { get; init; }
}

22 changes: 22 additions & 0 deletions src/Kook.Net.WebSocket/Entities/Audio/SoundtrackInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace Kook.Audio;

/// <summary>
/// Represents the information of a soundtrack.
/// </summary>
public readonly struct SoundtrackInfo
{
/// <summary>
/// Gets the name of the software from which the soundtrack audio originates
/// </summary>
public string? Software { get; init; }

/// <summary>
/// Gets the name of the music soundtrack
/// </summary>
public string? Music { get; init; }

/// <summary>
/// Gets the singer of the music soundtrack
/// </summary>
public string? Singer { get; init; }
}

0 comments on commit 5f233da

Please sign in to comment.