Fix streaming majors: PCM-only validation, stream-from-disk, ConcatStream offset, AsyncDisposable, HTTP cancellation, await ensureReady, seekBeyondBuffer offset-0 guard, negative WAV chunk guard
This commit is contained in:
@@ -392,7 +392,7 @@ public abstract class AudioPlayerService : IPlayerService, IAsyncDisposable
|
||||
await OnTrackSelected.Value.InvokeAsync();
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
public virtual async ValueTask DisposeAsync()
|
||||
{
|
||||
if (IsInitialized)
|
||||
{
|
||||
|
||||
@@ -90,7 +90,12 @@ public class StreamingAudioPlayerService : AudioPlayerService, IStreamingPlayerS
|
||||
|
||||
await NotifyStateChanged();
|
||||
|
||||
var mediaResult = await _trackMediaClient.GetTrackMedia(track.EntryKey);
|
||||
// Pass the streaming token to the HTTP layer so a navigation/track switch
|
||||
// aborts the server connection instead of leaving it draining bytes.
|
||||
var mediaResult = await _trackMediaClient.GetTrackMedia(
|
||||
track.EntryKey,
|
||||
byteOffset: 0,
|
||||
cancellationToken: _streamingCancellation.Token);
|
||||
if (!mediaResult.Success)
|
||||
{
|
||||
var technicalError = mediaResult.GetMessage();
|
||||
@@ -346,7 +351,10 @@ public class StreamingAudioPlayerService : AudioPlayerService, IStreamingPlayerS
|
||||
await NotifyStateChanged();
|
||||
|
||||
// Request new stream from offset
|
||||
var mediaResult = await _trackMediaClient.GetTrackMedia(_currentTrackId, byteOffset);
|
||||
var mediaResult = await _trackMediaClient.GetTrackMedia(
|
||||
_currentTrackId,
|
||||
byteOffset,
|
||||
cancellationToken: _streamingCancellation.Token);
|
||||
if (!mediaResult.Success || mediaResult.Value == null)
|
||||
{
|
||||
var technicalError = mediaResult.GetMessage() ?? "Failed to load audio from position";
|
||||
@@ -485,6 +493,25 @@ public class StreamingAudioPlayerService : AudioPlayerService, IStreamingPlayerS
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On component unmount we must cancel the in-flight streaming loop and tear
|
||||
/// down JS callbacks before the JS side's setInterval fires again with a
|
||||
/// stale DotNetObjectReference. ResetToIdle covers cancellation + JS stop
|
||||
/// + state reset; the base then disposes the JS player and its callbacks.
|
||||
/// </summary>
|
||||
public override async ValueTask DisposeAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
await ResetToIdle();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Disposal must not throw; any failure here is best-effort cleanup.
|
||||
}
|
||||
await base.DisposeAsync();
|
||||
}
|
||||
|
||||
private void AdaptBufferSize(int bytesRead, long readTimeMs)
|
||||
{
|
||||
// Adaptive buffer sizing based on network performance
|
||||
|
||||
Reference in New Issue
Block a user