Skip to content

feat(infra/local): B3 - local-files media source scaffold#320

Merged
LargeModGames merged 1 commit into
multi-sourcefrom
worktree-agent-a3b8e5bbd2187021b
Jun 22, 2026
Merged

feat(infra/local): B3 - local-files media source scaffold#320
LargeModGames merged 1 commit into
multi-sourcefrom
worktree-agent-a3b8e5bbd2187021b

Conversation

@LargeModGames

Copy link
Copy Markdown
Owner

Summary

  • Adds src/infra/local/mod.rs behind a new local-files Cargo feature (deps: symphonia, lofty)
  • Implements MediaSource for LocalSource: playlists() maps immediate subdirs to PlaylistInfo with RFC 8089-compliant file:// URIs; tracks() scans audio files and reads tags via lofty
  • Implements Streamer skeleton: opens the file, probes format with symphonia, and constructs a decoder -- Phase 3 sink wiring is marked with TODO(multi-source) comments
  • Gates the module in src/infra/mod.rs with #[cfg(feature = "local-files")]
  • All items carry #[allow(dead_code)] following Wave 0 convention -- nothing is wired into dispatch/UI yet

Key design decisions

  • path_to_file_uri uses url::Url::from_file_path (the url crate is already a direct dep) for correct percent-encoding of spaces and non-ASCII bytes
  • split_artists separates on ";", " / " (spaced slash), " & " -- bare "/" intentionally excluded so band names like AC/DC are not split
  • track_number = 0 (no tag) sorts after explicitly numbered tracks via u32::MAX sentinel
  • is_audio_file uses eq_ignore_ascii_case to avoid per-call heap allocation
  • Blocking I/O promotion to tokio::task::spawn_blocking is noted in TODO comments for Phase 3 wiring

Test plan

  • cargo build --no-default-features --features telemetry (slim build clean)
  • cargo build --no-default-features --features telemetry,local-files (local-files build clean)
  • cargo test --no-default-features --features telemetry (261 tests pass)
  • cargo test --no-default-features --features telemetry,local-files (278 tests pass, includes new local module tests)
  • cargo clippy --no-default-features --features telemetry -- -D warnings (clean)
  • cargo clippy --no-default-features --features telemetry,local-files -- -D warnings (clean)
  • cargo fmt --all (applied)
  • Tests are hermetic: use tempfile-backed temp dirs, generate minimal WAV fixtures inline

Add src/infra/local/ behind a new Cargo feature local-files, implementing
the MediaSource and Streamer traits from core::source for local audio files.

MediaSource:
- playlists() treats each immediate subdir of the root as a playlist, with
  RFC 8089-compliant file:// URIs (via url::Url::from_file_path), sorted
  alphabetically.
- tracks() lists audio files in a directory, reads tags with lofty, and
  builds TrackInfo with is_local=true. Untagged files fall back to the
  filename stem. Files without a track_number tag sort after numbered tracks
  (0 sentinel maps to u32::MAX).

Streamer skeleton:
- stream() opens the file, probes format with symphonia, and constructs a
  decoder to prove the decode pipeline is reachable.
- Phase 3 wiring (routing frames into the shared rodio sink) is marked with
  TODO(multi-source) comments; blocking I/O promotion to spawn_blocking is
  also noted for the wiring phase.

Quality:
- is_audio_file uses eq_ignore_ascii_case (no heap allocation vs to_lowercase).
- split_artists separates on ';', ' / ' (spaced), ' & '; bare '/' is not a
  separator so band names like AC/DC are preserved intact.
- path_to_file_uri uses url::Url::from_file_path for correct percent-encoding
  of spaces and non-ASCII bytes; round-trip is handled by Url::to_file_path.
- All items marked #[allow(dead_code)] following Wave 0 convention.
- Unit tests: URI round-trip, extension detection, artist splitting, directory
  scan, tag fallback, and decoder construction. Tests use tempfile-backed dirs
  for full hermeticity.
@LargeModGames LargeModGames merged commit 6f70101 into multi-source Jun 22, 2026
5 checks passed
@LargeModGames LargeModGames deleted the worktree-agent-a3b8e5bbd2187021b branch June 22, 2026 12:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant