pub trait Source:
MaybeSend
+ MaybeSync
+ 'static {
Show 24 methods
// Required methods
fn advance(&self, n: u64);
fn len(&self) -> Option<u64>;
fn phase_at(&self, range: Range<u64>) -> SourcePhase;
fn position(&self) -> u64;
fn read_at(
&mut self,
offset: u64,
buf: &mut [u8],
) -> StreamResult<ReadOutcome>;
fn set_position(&self, pos: u64);
fn timeline(&self) -> Timeline;
fn wait_range(
&mut self,
range: Range<u64>,
timeout: Option<Duration>,
) -> StreamResult<WaitOutcome>;
// Provided methods
fn abr_handle(&self) -> Option<AbrHandle> { ... }
fn as_segment_layout(&self) -> Option<Arc<dyn SegmentLayout>> { ... }
fn clear_variant_fence(&mut self) { ... }
fn commit_seek_landing(&mut self, _anchor: Option<SourceSeekAnchor>) { ... }
fn current_segment_range(&self) -> Option<Range<u64>> { ... }
fn current_variant(&self) -> Option<VariantInfo> { ... }
fn format_change_segment_range(&self) -> StreamResult<Range<u64>> { ... }
fn has_variant_change_pending(&self) -> bool { ... }
fn is_empty(&self) -> bool { ... }
fn make_notify_fn(&self) -> Option<Box<dyn Fn() + Send + Sync>> { ... }
fn media_info(&self) -> Option<MediaInfo> { ... }
fn notify_waiting(&self) { ... }
fn phase(&self) -> SourcePhase { ... }
fn seek_time_anchor(
&mut self,
_position: Duration,
) -> StreamResult<Option<SourceSeekAnchor>> { ... }
fn set_seek_epoch(&mut self, _seek_epoch: u64) { ... }
fn take_reader_hooks(&mut self) -> Option<SharedHooks> { ... }
}Expand description
Sync random-access source.
Provides sync interface for waiting and reading data at arbitrary offsets.
Reader wraps this directly to provide Read + Seek.
Methods take &mut self to allow sources to maintain internal state
(e.g., progress tracking, segment index updates).
Required Methods§
Sourcefn len(&self) -> Option<u64>
fn len(&self) -> Option<u64>
Total length if known.
Streaming sources may block briefly until the HTTP response headers arrive (Content-Length discovery).
Sourcefn phase_at(&self, range: Range<u64>) -> SourcePhase
fn phase_at(&self, range: Range<u64>) -> SourcePhase
Point-in-time snapshot of the source phase for the given range.
Returns the current SourcePhase without blocking. Used internally
by wait_range() implementations for fast-path dispatch.
Sourcefn position(&self) -> u64
fn position(&self) -> u64
Current byte position in the source’s virtual byte space.
HLS delegates to active variant; file owns its own atomic cursor.
Sourcefn read_at(&mut self, offset: u64, buf: &mut [u8]) -> StreamResult<ReadOutcome>
fn read_at(&mut self, offset: u64, buf: &mut [u8]) -> StreamResult<ReadOutcome>
Read data at offset into buffer.
Returns ReadOutcome::Bytes with a non-zero byte count on
progress, ReadOutcome::Pending with a typed
PendingReason when no progress is possible this call (seek
pending, variant fence, eviction), or ReadOutcome::Eof at
natural end-of-stream.
§Errors
Returns an error if the read fails or the source is in an invalid state.
Sourcefn set_position(&self, pos: u64)
fn set_position(&self, pos: u64)
Absolute set of the byte cursor — used by [Stream::seek] and
post-seek landings. Sources implement this via the same atomic
cursor that backs Self::position / Self::advance.
Sourcefn timeline(&self) -> Timeline
fn timeline(&self) -> Timeline
Get shared playback timeline.
Timeline is the single source of truth for playback state across all stream types (segmented and non-segmented). Sources own their Timeline and hand out cheap Arc clones to downstream consumers (reader, audio FSM, Downloader peers).
Sourcefn wait_range(
&mut self,
range: Range<u64>,
timeout: Option<Duration>,
) -> StreamResult<WaitOutcome>
fn wait_range( &mut self, range: Range<u64>, timeout: Option<Duration>, ) -> StreamResult<WaitOutcome>
Wait for data in range to be available.
timeout is the maximum wait time before returning an
implementation-defined non-ready outcome (typically a typed
“budget exceeded” error). Pass None to wait until the range
is ready or the source’s internal cancel signal fires — used
for Stream::seek, where giving up on
a timer would silently drop the seek under slow connections.
Some(WAIT_RANGE_TIMEOUT) is the cooperative-yield path used
by the audio worker’s read loop.
§Errors
Returns an error if the wait is cancelled or the underlying storage fails.
Provided Methods§
Sourcefn abr_handle(&self) -> Option<AbrHandle>
fn abr_handle(&self) -> Option<AbrHandle>
Current ABR handle for runtime mode/bandwidth control.
Adaptive sources (HLS) return the peer’s AbrHandle so callers —
queue, FFI, UI — can switch variant or cap bandwidth mid-playback.
Non-adaptive sources (File) keep the default None.
Sourcefn as_segment_layout(&self) -> Option<Arc<dyn SegmentLayout>>
fn as_segment_layout(&self) -> Option<Arc<dyn SegmentLayout>>
Optional shared segment-layout handle for segment-aware decoders.
Segment-aware decoders (fMP4 segment demuxer) call this once at
open to grab a lock-free, Arc-shareable view over the segment
table — independent of the byte cursor passed to the decoder
through Read + Seek. Default None for non-segmented sources.
Sourcefn clear_variant_fence(&mut self)
fn clear_variant_fence(&mut self)
Clear variant fence, allowing reads from the next variant.
Called when the decoder is recreated after ABR switch. Default no-op for non-HLS sources.
Sourcefn commit_seek_landing(&mut self, _anchor: Option<SourceSeekAnchor>)
fn commit_seek_landing(&mut self, _anchor: Option<SourceSeekAnchor>)
Commit the actual post-seek landing after decoder.seek(...).
Segmented sources can use this hook to reconcile source-local state
with the authoritative landed reader position in Timeline.
Default no-op for sources that do not need post-seek reconciliation.
Sourcefn current_segment_range(&self) -> Option<Range<u64>>
fn current_segment_range(&self) -> Option<Range<u64>>
Current segment byte range (HLS-only).
Transitional — removed in Plan 06 once the audio FSM consumes
segment boundaries through SegmentLayout.
Sourcefn current_variant(&self) -> Option<VariantInfo>
fn current_variant(&self) -> Option<VariantInfo>
Current variant’s full metadata. Adaptive sources (HLS) return
the live VariantInfo for the active variant — pulled from the
peer on every call so the UI never sees a stale label. Non-adaptive
sources keep the default None.
Sourcefn format_change_segment_range(&self) -> StreamResult<Range<u64>>
fn format_change_segment_range(&self) -> StreamResult<Range<u64>>
Byte range of the header (init segment or first served segment) the decoder must read to re-establish container state after a format change (HLS ABR cross-codec switch).
Returns Ok(range) — header byte range that apply_format_change
seeks to and the decoder factory’s probe reads.
§Errors
Err(SourceError::FormatChangeNotApplicable) — source has no
HLS-style format-change recovery (file source — default impl) or
the active HLS variant was activated with served_from > 0 so
the init prefix lives outside the served virtual byte range.
Callers should fall back to a non-init recovery anchor (e.g.
the current segment boundary).
Transitional — removed in Plan 06.
Sourcefn has_variant_change_pending(&self) -> bool
fn has_variant_change_pending(&self) -> bool
true if a cross-variant transition is in-flight and read_at /
wait_range are short-circuited to Pending(VariantChange) /
Interrupted until the decoder acks the switch via
clear_variant_fence (HLS) or equivalent.
Sources without a variant fence keep the default false. Used by
the audio decode loop to break out of Ok(Pending(_)) retry spin
when Symphonia / other demuxers absorb the underlying
VariantChangeError and surface only an opaque pending — without
this polled check the loop would yield forever while the fence
stays closed waiting for a recreate that never starts.
Sourcefn is_empty(&self) -> bool
fn is_empty(&self) -> bool
Whether the source currently reports zero bytes. Default mirrors
self.len() returning 0 (or being unknown — both are treated as
“no readable bytes yet” for the conventional len/is_empty pair).
Sourcefn make_notify_fn(&self) -> Option<Box<dyn Fn() + Send + Sync>>
fn make_notify_fn(&self) -> Option<Box<dyn Fn() + Send + Sync>>
Create a callback that wakes blocked wait_range() without holding
the SharedStream mutex.
The returned closure captures only the underlying condvar/notify
primitive, so calling it from the main thread cannot deadlock even
when the worker thread holds the SharedStream lock inside read().
Default returns None (no blocking waits to wake).
Sourcefn media_info(&self) -> Option<MediaInfo>
fn media_info(&self) -> Option<MediaInfo>
Get media info if available.
Sourcefn notify_waiting(&self)
fn notify_waiting(&self)
Wake any blocked wait_range() calls.
Called after Timeline::initiate_seek() to ensure immediate response
from threads sleeping on condvars. Default no-op for sources without
blocking waits.
Sourcefn phase(&self) -> SourcePhase
fn phase(&self) -> SourcePhase
Overall source readiness at the current timeline position.
Uses the source’s internal knowledge of chunk/segment boundaries to determine if the next read operation can proceed without blocking.
Unlike phase_at(range) which checks a specific byte range,
this method lets the source decide the appropriate granularity.
Default checks a single byte at the current position. HLS overrides with segment-aware logic, File with 32KB-window logic.
Sourcefn seek_time_anchor(
&mut self,
_position: Duration,
) -> StreamResult<Option<SourceSeekAnchor>>
fn seek_time_anchor( &mut self, _position: Duration, ) -> StreamResult<Option<SourceSeekAnchor>>
Resolve position to a source-specific seek anchor.
Segmented sources (HLS) should map time to a deterministic segment
boundary and byte offset. Non-segmented sources return Ok(None).
The caller is expected to set stream position to byte_offset and
perform decoder reset/recreation using this anchor.
§Errors
Returns an error when the source cannot resolve the anchor.
Sourcefn set_seek_epoch(&mut self, _seek_epoch: u64)
fn set_seek_epoch(&mut self, _seek_epoch: u64)
Set current seek epoch for stale request invalidation.
HLS uses this to drop in-flight network/segment requests that belong to previous seeks. Non-seek-aware sources keep the default no-op.
Sourcefn take_reader_hooks(&mut self) -> Option<SharedHooks>
fn take_reader_hooks(&mut self) -> Option<SharedHooks>
Build a fresh reader-side hooks instance.
Returned by Source-impls that want to expose reader-side events
(HlsSource, FileSource). The audio pipeline takes the hook
at decoder creation/recreation time and threads it into the
HookedDecoder wrapper. Default None keeps mock and test
sources unhooked.
take_* is a misnomer: each call must return a fresh hook
instance, because decoder recreation (ABR / format change)
rebuilds the wrapper and the new hook needs a clean state
cursor.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".