# Smart Preloading Implementation This document describes the smart preloading system that automatically queues downloads for upcoming tracks in the playback queue. ## Overview The preloading system monitors playback and automatically queues background downloads for the next 3 tracks in the queue. This ensures smooth playback transitions and offline availability without requiring manual downloads. ## Architecture ### Backend (Rust) **Smart Cache Engine** - `/src-tauri/src/download/cache.rs` - Manages preload configuration - Default settings: preload 3 tracks, works on any connection (not wifi-only) - Storage limit: 10GB - Album affinity tracking (future feature) **Queue Manager** - `/src-tauri/src/player/queue.rs` - New method: `get_upcoming(count)` returns next N tracks - Respects shuffle order - Handles repeat modes (Off, All, One) - Wraps around when RepeatMode::All is enabled **Preload Command** - `/src-tauri/src/commands/player.rs` - `player_preload_upcoming` - Main preload endpoint - Checks SmartCache configuration - Gets upcoming tracks from queue - Skips already downloaded/queued items - Queues new downloads with low priority (-100) - Returns stats: queued_count, already_downloaded, skipped **Configuration Commands** - `player_set_cache_config` - Update preload settings - `player_get_cache_config` - Get current settings ### Frontend (TypeScript/Svelte) **Preload Service** - `/src/lib/services/preload.ts` - Main function: `preloadUpcomingTracks()` - Automatically gets current user ID from auth store - Calls backend preload command - Fails silently - never interrupts playback - Logs meaningful results only **Integration Points** - `/src/lib/services/playerEvents.ts` 1. **On playback start** - When state changes to "playing" 2. **On track advance** - After successfully advancing to next track ## How It Works ### Playback Flow ``` User plays track/queue ↓ Backend starts playback ↓ Emits "state_changed" event with "playing" ↓ playerEvents.handleStateChanged() catches event ↓ Calls preloadUpcomingTracks() ↓ Backend queues downloads for next 3 tracks (if not already downloaded) ``` ### Track Advance Flow ``` Track ends (or user clicks next) ↓ playerEvents.handlePlaybackEnded() or manual next() ↓ Calls player_next backend command ↓ Backend plays next track, emits "state_changed" ↓ Calls preloadUpcomingTracks() again ↓ Queue is shifted forward, new track gets preloaded ``` ## Configuration ### Default Settings ```typescript { queuePrecacheEnabled: true, queuePrecacheCount: 3, albumAffinityEnabled: true, albumAffinityThreshold: 3, storageLimit: 10737418240, // 10GB wifiOnly: false } ``` ### Updating Configuration ```typescript import { updateCacheConfig } from '$lib/services/preload'; await updateCacheConfig({ queuePrecacheCount: 5, // Preload 5 tracks instead of 3 wifiOnly: true // Only preload on WiFi }); ``` ## Features ### Intelligent Queueing - ✅ Checks if tracks are already downloaded - ✅ Skips tracks already in download queue - ✅ Low priority (-100) so user-initiated downloads go first - ✅ Respects shuffle and repeat modes - ✅ No duplicate downloads ### Offline First - ✅ Existing `create_media_item()` in player.rs checks local downloads first - ✅ Preloading ensures next tracks become local over time - ✅ Seamless offline playback without manual intervention ### Non-Intrusive - ✅ Background operation - never blocks playback - ✅ Fails silently - errors are logged but don't affect UX - ✅ Automatic - no user interaction required - ✅ Configurable - users can adjust or disable ## Files Changed ### Backend - `src-tauri/src/player/queue.rs` - Added `get_upcoming()` method - `src-tauri/src/download/cache.rs` - Made `CacheConfig` serializable, updated defaults - `src-tauri/src/commands/player.rs` - Added preload commands and `SmartCacheWrapper` - `src-tauri/src/lib.rs` - Initialized SmartCache, registered commands ### Frontend - `src/lib/services/preload.ts` - New preload service (created) - `src/lib/services/playerEvents.ts` - Integrated preload triggers ### Configuration - `src-tauri/Cargo.toml` - Added tempfile dev dependency for tests ## Testing ### Rust Tests ```bash cd src-tauri cargo test queue::tests::test_get_upcoming cargo test cache::tests::test_default_config ``` All tests pass ✅ ### Manual Testing 1. **Start playback** - Play a queue of 5+ tracks - Check console for: `[Preload] Queued N track(s) for background download` - Verify download queue shows 3 pending downloads with priority -100 2. **Track advance** - Let track finish or click next - Check console for new preload log - Verify queue shifts (old track 2 becomes current, new track gets queued) 3. **Repeat mode** - Enable Repeat All - Play to end of queue - Verify wraps around and continues preloading 4. **Already downloaded** - Download all tracks in an album - Play the album - Check logs show: `already_downloaded: 3, queued: 0` ## Future Enhancements 1. **Album Affinity** - If user plays 3+ tracks from an album, auto-download the rest 2. **WiFi Detection** - Respect `wifi_only` setting on mobile 3. **Storage Management** - Auto-evict LRU items when storage limit reached 4. **Smart Priority** - Boost priority as track gets closer in queue 5. **Bandwidth Throttling** - Limit download speed to not interfere with streaming ## Troubleshooting ### Preload not working - Check console for `[Preload]` logs - Verify user is logged in: `auth.getUserId()` returns value - Check SmartCache config: `queuePrecacheEnabled` should be true ### Downloads not starting - Preload only queues downloads, doesn't start them - Check download manager is processing queue - Verify backend has download worker running ### Too many downloads - Reduce `queuePrecacheCount` in config - Enable `wifiOnly` mode - Adjust `storageLimit` ## Performance Impact - **Minimal** - Background downloads use low priority - **Non-blocking** - Async operation, no playback delay - **Bandwidth-friendly** - Only downloads when needed - **Storage-aware** - Respects configured limits ## Summary Smart preloading transforms JellyTau into an offline-first music player. By automatically queueing downloads for upcoming tracks, it ensures seamless playback and offline availability without requiring users to manually manage downloads. The system is intelligent (checks what's already downloaded), non-intrusive (fails silently), and configurable (users can adjust or disable).