Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ and Squeezelite.
- [x] [Chromecast](https://developers.google.com/cast)
- [x] Gapless playback and crossfading
- [x] Supports 20+ codecs: MP3, OGG, FLAC, WAV, AAC, Opus, and more
- [x] Smart HTTP file cache — parallel multi-part downloads, LRU eviction, auto-skips live streams

### APIs & integrations
- [x] [gRPC API](https://buf.build/tsiry/rockboxapis/docs/main:rockbox.v1alpha1)
Expand Down Expand Up @@ -452,6 +453,38 @@ parsed and displayed.
| `upnp_renderer_port` | `7880` | MediaRenderer HTTP port |
| `upnp_friendly_name` | `"Rockbox"` | Display name shown to control points |

### HTTP file cache

Remote audio files are cached on disk automatically. Repeat plays are instant
with no network traffic. Files are downloaded in the background using parallel
range-request parts so playback is never delayed.

```toml
# All fields are optional — defaults shown.
cache_enabled = true
cache_dir = "~/.config/rockbox.org/cache"
cache_max_size_mb = 512 # total cache budget in MB
cache_min_free_space_mb = 100 # always keep this much free on disk
cache_parallel_parts = 4 # concurrent HTTP Range parts per file

# URLs containing any of these substrings bypass the cache.
# Prevents live radio / HLS streams from filling the cache.
cache_no_cache_patterns = ["icecast", ".m3u8", "live"]
```

**How it works:**

| Step | What happens |
| ---- | ------------ |
| 1 | On open, the SHA-256 of the URL is checked against `cache_dir`. |
| 2 | **Hit**: the local file is opened instantly; all seeks are O(1) — no network. |
| 3 | **Miss**: the live HTTP stream opens normally (zero latency) AND a background thread splits the file into `cache_parallel_parts` ranges and fetches them concurrently via `pwrite` into a pre-allocated file. |
| 4 | When the download completes and is verified, the file is atomically renamed. The next open is a cache hit. |
| 5 | When the cache exceeds `cache_max_size_mb`, the least-recently-used files are evicted to make room. |

URLs with no `Content-Length` (infinite/live streams) are **never** cached —
caching is skipped automatically before a download is even started.

---

## 🚚 Installation
Expand Down
15 changes: 15 additions & 0 deletions crates/cache/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "rockbox-cache"
version = "0.1.0"
edition = "2021"

[lib]
name = "rockbox_cache"
crate-type = ["rlib"]

[dependencies]
once_cell = "1.17.1"
sha2 = "0.10"
libc = "0.2.168"
reqwest = { version = "0.12.5", features = ["blocking", "rustls-tls-native-roots"], default-features = false }
tracing = { workspace = true }
Loading
Loading