-
Notifications
You must be signed in to change notification settings - Fork 0
Playlists and History
Relevant source files
The following files were used as context for generating this wiki page:
This section documents the persistence layer of the Aurora daemon, specifically how user-generated data such as playlists, liked songs, and playback history are stored in SQLite and managed through the StateStruct.
Aurora uses a SQLite database located at ~/.config/aurora-player/aurora.db daemon/src/helpers/db.rs:9-13. The database is initialized with PRAGMA journal_mode=WAL and foreign_keys=ON to ensure performance and referential integrity daemon/src/helpers/db.rs:16-17.
The migrate function daemon/src/helpers/db.rs:23-54 defines the following schema:
| Table | Purpose | Key Columns |
|---|---|---|
songs |
Cache of indexed file metadata. |
id (PK), path, mtime, art_path
|
playlists |
Metadata for user-created playlists. |
id (PK), title
|
playlist_songs |
Junction table for songs in playlists. |
playlist_id (FK), song_id, position
|
liked_songs |
Set of song IDs marked as favorites. |
song_id (PK) |
history |
Recently played tracks. |
song_id (PK), played_at
|
Sources: daemon/src/helpers/db.rs:24-54
Playlist operations are split between high-level handlers that communicate with the client and low-level helpers that interact with the rusqlite connection.
When a user requests a playlist, the system performs a multi-stage join between the database and the in-memory index.
Title: Playlist Data Retrieval Flow
sequenceDiagram
participant H as handlers/playlist.rs
participant S as StateStruct
participant DB as SQLite (playlists/playlist_songs)
participant I as In-Memory Index
H->>S: get_playlist(uuid)
S->>DB: SELECT title, song_ids WHERE playlist_id
DB-->>S: (title, Vec<song_id>)
loop For each song_id
S->>I: get(song_id)
I-->>S: SongMeta
S->>S: get_art(song_id)
end
S-->>H: Playlist { title, songs: Vec<Song> }
Sources: daemon/src/helpers/playlist.rs:11-60, daemon/src/handlers/playlist.rs:152-177
Playlist modification functions are defined in helpers/playlist.rs and typically wrapped in tokio::task::spawn_blocking to prevent blocking the async executor during disk I/O daemon/src/helpers/playlist.rs:154-163.
-
create_playlist: Generates a UUID-v5 based on the title and inserts it into theplayliststable daemon/src/helpers/playlist.rs:150-165. -
add_songs_to_playlist: Inserts multiple song IDs intoplaylist_songs. Note that it usesINSERT OR IGNOREto prevent duplicates daemon/src/helpers/playlist.rs:223-242. -
playlist_list: Retrieves all playlists viaget_all_playlists, which also fetches the first 4 song art paths for the UI preview daemon/src/helpers/playlist.rs:62-147.
Sources: daemon/src/helpers/playlist.rs:1-242, daemon/src/handlers/playlist.rs:1-178
Liked songs are managed as a HashSet<Uuid> in the StateStruct for O(1) lookups during playback (to show the "liked" status of the current song) and persisted in the liked_songs table.
-
load_liked: Called during daemon startup to populate the in-memory set daemon/src/helpers/liked_store.rs:6-30. -
like_song: Inserts the ID into the in-memoryliked_idsand the databaseliked_songstable daemon/src/handlers/liked.rs:9-17. -
unlike_song: Removes the ID from both the set and the database daemon/src/handlers/liked.rs:19-31.
Sources: daemon/src/helpers/liked_store.rs:1-63, daemon/src/handlers/liked.rs:1-51
The history system tracks recently played songs, capped at a maximum of 30 entries daemon/src/helpers/history.rs:6.
-
push_history: Adds a song to the front of aVecDeque. If the song was already at the front, it is ignored. If it existed elsewhere in the history, it is moved to the front to avoid duplicates daemon/src/helpers/history.rs:58-65. -
save_history: Persists the history by clearing thehistorytable and re-inserting the current deque. It uses a transaction (BEGIN/COMMIT) and calculates aplayed_atvalue based oni64::MAXminus the index to maintain order daemon/src/helpers/history.rs:36-56.
Title: Persistence Layer Code Entities
classDiagram
class StateStruct {
+Db db
+HashMap index
+HashSet liked_ids
+VecDeque history
+get_playlist(Uuid)
+get_all_playlists()
}
class PlaylistHandlers {
+playlist_create()
+playlist_add_songs()
+playlist_get()
}
class LikedStore {
+load_liked(Db)
+add_liked(Db, Uuid)
+remove_liked(Db, Uuid)
}
class HistoryHelpers {
+load_history(Db)
+save_history(Db, VecDeque)
+push_history(VecDeque, Uuid)
}
PlaylistHandlers ..> StateStruct : locks & accesses
StateStruct ..> LikedStore : uses for persistence
StateStruct ..> HistoryHelpers : uses for persistence
Sources: daemon/src/helpers/history.rs:1-66, daemon/src/types/mod.rs:1-14, daemon/src/helpers/liked_store.rs:1-63
Persistence operations return std::io::Result or anyhow::Result. The to_io helper daemon/src/helpers/db.rs:56-58 converts rusqlite::Error into std::io::Error for consistency. If a database operation fails in a handler, an aurora_protocol::Response::Error is sent back to the client with a specific error ID (e.g., ID 8 for rename failures, ID 7 for delete failures) daemon/src/handlers/playlist.rs:19-32.
Sources: daemon/src/helpers/db.rs:56-58, daemon/src/handlers/playlist.rs:19-55
Overview
aurora-daemon
- Background Service
- Startup & State Init
- Request Handlers & Dispatch
- Playback Engine & Audio
- Library Indexing & Watching
- Playlists, Liked & History
- Background Threads
aurora-protocol
aurora-player
Reference