using DeepDrftModels.Enums; namespace DeepDrftContent.Processors.Opus; /// /// The outcome of resolving a track + requested to a concrete artifact /// (Phase 18.2; read-path streaming). Carries an open, seekable, disk-backed /// over the artifact's bytes — never a buffered byte[], so a ~220 MB Opus file or ~970 MB lossless /// source is never materialized in a managed array per request. Also carries the content-type that matches /// what was actually returned, and the format actually served — which may differ from the requested /// one when the C2 fallback fires (Opus requested, no Opus artifact → the lossless artifact + its /// content-type). The delivery layer (18.3) sets the response Content-Type from /// so the eventual decoder picks the right decoder for the bytes it receives. /// /// Ownership: the resolver opens the stream; the caller takes ownership. On the success path the caller hands /// to File(..., enableRangeProcessing: true), which disposes it after the /// response. On any pre-handoff throw the caller disposes this instance (which disposes the stream) so the /// underlying never leaks — mirroring the lossless disk-stream path's catch-path /// disposal. /// /// /// An open, seekable, disk-backed stream over the resolved artifact. The caller owns it. /// The MIME type of the bytes in (e.g. audio/ogg /// for Opus, or the source's real MIME for lossless). /// The format actually returned. Equal to the requested format on a direct /// hit; when an Opus request fell back. public sealed record ResolvedAudio(Stream Stream, string ContentType, AudioFormat ResolvedFormat) : IDisposable, IAsyncDisposable { /// True when an Opus request was served the lossless artifact because no Opus existed (C2). public bool DidFallBack(AudioFormat requested) => requested != ResolvedFormat; public void Dispose() => Stream.Dispose(); public ValueTask DisposeAsync() => Stream.DisposeAsync(); }