playback: a cached track plays without asking Soulseek where it lives

Hopping between songs of an already-cached album still ran the full
"finding best source…" resolve for audio sitting complete on disk — a
second of popup between every click. The player now remembers the source
each stream item was queued from (localStorage, LRU-capped at 400) and,
before any search, asks the backend whether that exact file is
byte-complete in the stream cache. If it is, the track plays those bytes
immediately: no resolver, no popup, and no online requirement — cached
audio is playable offline, so the check sits before requireOnline.

The memory is a hint, never a promise. It is written eagerly when an item
is queued to PLAY, because a source that never delivers leaves no complete
cache file and the byte-complete probe rejects it later at no cost;
eviction and half-finished transfers fall back to the normal resolver the
same way. First play of a track records it, every play after that is
instant.
This commit is contained in:
KeelrLeek committed 2026-08-03 16:08:51 -05:00
1 parent b33d403634
commit f55562f0ab
4 files changed
+138

No files matched your search

+20
View File
@@ -3900,6 +3900,26 @@ pub async fn stream_waveform(
result
}
/// Is this exact stream source already fully cached on disk?
///
/// The catalog's play paths ask BEFORE running a Soulseek resolve: a complete
/// cache file can play immediately — even offline — and the search would only
/// rediscover the peer that filled it. Anything less than a byte-complete
/// file answers false, so eviction and half-finished transfers fall back to
/// the normal resolver on their own.
#[tauri::command]
pub fn stream_cache_ready(
app: tauri::AppHandle,
username: String,
path: String,
size: u64,
) -> bool {
let Some(cache) = playback::cache_path(&app, &username, &path) else {
return false;
};
size > 0 && matches!(std::fs::metadata(&cache), Ok(md) if md.len() == size)
}
/// A waveform plus how much of the track it actually describes. `coverage`
/// is the byte share of the transfer the peaks were decoded from (1.0 for a
/// complete file); the peaks span exactly that prefix of the track and
+1
View File
@@ -115,6 +115,7 @@ pub fn run() {
commands::preload_stream,
commands::preload_cached_stream,
commands::stream_waveform,
commands::stream_cache_ready,
preview::preview_resolve,
preview::preview_prewarm,
preview::preview_load,