From 654fcbccf64fcff7c86df8a3fbe9f195a37f5a8f Mon Sep 17 00:00:00 2001 From: SKProCH Date: Sun, 1 Sep 2024 17:56:15 +0300 Subject: [PATCH 1/3] Add support for track overriding for initial track --- src/Lavalink4NET/Players/LavalinkPlayerHandle.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Lavalink4NET/Players/LavalinkPlayerHandle.cs b/src/Lavalink4NET/Players/LavalinkPlayerHandle.cs index bbbf1047..17d1be31 100644 --- a/src/Lavalink4NET/Players/LavalinkPlayerHandle.cs +++ b/src/Lavalink4NET/Players/LavalinkPlayerHandle.cs @@ -198,7 +198,8 @@ private async ValueTask CreatePlayerAsync(CancellationToken cancellatio if (initialTrack.Reference.IsPresent) { - playerProperties = playerProperties with { TrackData = initialTrack.Track!.ToString(), }; + var playableTrack = await initialTrack.Reference.Track.GetPlayableTrackAsync(cancellationToken); + playerProperties = playerProperties with { TrackData = playableTrack.ToString()}; } else { From a3407b1ea1346d805ad3c53d5fb8f28c8768c841 Mon Sep 17 00:00:00 2001 From: SKProCH Date: Sun, 1 Sep 2024 17:56:41 +0300 Subject: [PATCH 2/3] Add initial position to track create options --- src/Lavalink4NET/Players/LavalinkPlayerHandle.cs | 5 +++++ src/Lavalink4NET/Players/LavalinkPlayerOptions.cs | 8 ++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Lavalink4NET/Players/LavalinkPlayerHandle.cs b/src/Lavalink4NET/Players/LavalinkPlayerHandle.cs index 17d1be31..60614dc3 100644 --- a/src/Lavalink4NET/Players/LavalinkPlayerHandle.cs +++ b/src/Lavalink4NET/Players/LavalinkPlayerHandle.cs @@ -211,6 +211,11 @@ private async ValueTask CreatePlayerAsync(CancellationToken cancellatio } } + if (_options.Value.InitialPosition is not null) + { + playerProperties = playerProperties with { Position = _options.Value.InitialPosition.Value }; + } + if (_options.Value.InitialVolume is not null) { playerProperties = playerProperties with { Volume = _options.Value.InitialVolume.Value, }; diff --git a/src/Lavalink4NET/Players/LavalinkPlayerOptions.cs b/src/Lavalink4NET/Players/LavalinkPlayerOptions.cs index 86ea56c9..5023b205 100644 --- a/src/Lavalink4NET/Players/LavalinkPlayerOptions.cs +++ b/src/Lavalink4NET/Players/LavalinkPlayerOptions.cs @@ -1,4 +1,6 @@ -namespace Lavalink4NET.Players; +using System; + +namespace Lavalink4NET.Players; using Lavalink4NET.Rest.Entities.Tracks; @@ -12,6 +14,8 @@ public record class LavalinkPlayerOptions public ITrackQueueItem? InitialTrack { get; set; } + public TimeSpan? InitialPosition { get; set; } + public TrackLoadOptions InitialLoadOptions { get; set; } public float? InitialVolume { get; set; } @@ -19,4 +23,4 @@ public record class LavalinkPlayerOptions public bool SelfDeaf { get; set; } public bool SelfMute { get; set; } -} +} \ No newline at end of file From 7a489bcc12a6a3c241e90927f50f273036f27941 Mon Sep 17 00:00:00 2001 From: SKProCH Date: Sun, 1 Sep 2024 18:11:11 +0300 Subject: [PATCH 3/3] Add exception handling for the CreatePlayerAsync in LavalinkPlayerHandle --- .../Players/LavalinkPlayerHandle.cs | 25 ++++++++++++++----- src/Lavalink4NET/Players/PlayerManager.cs | 5 ++-- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/Lavalink4NET/Players/LavalinkPlayerHandle.cs b/src/Lavalink4NET/Players/LavalinkPlayerHandle.cs index 60614dc3..949b4213 100644 --- a/src/Lavalink4NET/Players/LavalinkPlayerHandle.cs +++ b/src/Lavalink4NET/Players/LavalinkPlayerHandle.cs @@ -141,12 +141,25 @@ private async ValueTask CompleteAsync(bool isVoiceServerUpdated, CancellationTok if (_value is TaskCompletionSource taskCompletionSource) { // _value is automatically set by CreatePlayerAsync - var player = await CreatePlayerAsync(cancellationToken).ConfigureAwait(false); - - taskCompletionSource.TrySetResult(player); - - Interlocked.Decrement(ref Diagnostics.PendingHandles); - Interlocked.Increment(ref Diagnostics.ActivePlayers); + try + { + // CreatePlayerAsync can throw if request to lavalink fails + // We should handle this to avoid never completed lavalink player handle + var player = await CreatePlayerAsync(cancellationToken).ConfigureAwait(false); + + taskCompletionSource.TrySetResult(player); + + Interlocked.Decrement(ref Diagnostics.PendingHandles); + Interlocked.Increment(ref Diagnostics.ActivePlayers); + } + catch (Exception e) + { + // Here we're passing CancellationToken.None to ensure what the player disposing event will properly + // clean up this handle from cache + await _playerContext.LifecycleNotifier!.NotifyDisposeAsync(_guildId, CancellationToken.None); + taskCompletionSource.TrySetException(e); + await DisposeAsync(); + } } else { diff --git a/src/Lavalink4NET/Players/PlayerManager.cs b/src/Lavalink4NET/Players/PlayerManager.cs index 376c5bd3..7f7df6aa 100644 --- a/src/Lavalink4NET/Players/PlayerManager.cs +++ b/src/Lavalink4NET/Players/PlayerManager.cs @@ -312,11 +312,10 @@ async ValueTask IPlayerLifecycleNotifier.NotifyDisposeAsync(ulong guildId, Cance await using var _ = playerHandle.ConfigureAwait(false); - Debug.Assert(playerHandle.Player is not null); - Debug.Assert(playerHandle.Player is { State: PlayerState.Destroyed, }); - + // Player can be null if lavalink node will throw while creating player if (playerHandle.Player is not null) { + Debug.Assert(playerHandle.Player is { State: PlayerState.Destroyed, }); var eventArgs = new PlayerDestroyedEventArgs(playerHandle.Player); await PlayerDestroyed