jellytau/PRELOADING.md

6.4 KiB

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

{
  queuePrecacheEnabled: true,
  queuePrecacheCount: 3,
  albumAffinityEnabled: true,
  albumAffinityThreshold: 3,
  storageLimit: 10737418240, // 10GB
  wifiOnly: false
}

Updating Configuration

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

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).