ok
This commit is contained in:
+34
-7
@@ -139,7 +139,14 @@ volume, and repeat mode.
|
||||
Selecting, deleting, or creating a tab stops playback. Tracks are de-duplicated
|
||||
by normalized source path when they are appended. Every playlist mutation is
|
||||
written in one `keystore` transaction. `playlists-for-<username>` contains the
|
||||
ordered playlist GUIDs; each GUID key contains that playlist's name and tracks.
|
||||
ordered open playlist GUIDs; `saved-playlists-for-<username>` contains the saved
|
||||
library playlist GUIDs. Each GUID key contains one playlist's name and tracks.
|
||||
Both indexes are persisted atomically; a value is deleted only when neither
|
||||
index refers to it. Closing a saved tab retains its library entry.
|
||||
`restore-playlist-context` reuses the same in-memory object for a saved playlist
|
||||
and its open tab, so track edits and renaming update both views. Old stores
|
||||
without a saved index restore their original tabs without automatically saving
|
||||
them in the library.
|
||||
Loading validates every stored track independently against all configured
|
||||
library roots, so one playlist can safely combine multiple libraries.
|
||||
`language-for-<username>` stores the user's selected interface language in the
|
||||
@@ -224,7 +231,7 @@ serves static assets from [`public/`](public/) and exposes these API endpoints:
|
||||
|
||||
| Method | Route | Responsibility |
|
||||
| --- | --- | --- |
|
||||
| `GET` | `/api/state` | Return the complete current state; also refresh network-renderer information. |
|
||||
| `GET` | `/api/state` | Return current state, omitting unchanged tracks when `playlistVersion` matches; also refresh network-renderer information. |
|
||||
| `POST` | `/api/discover` | Start asynchronous discovery and return the current state. |
|
||||
| `POST` | `/api/command/:command` | Execute a command with its JSON request body and return the updated state. |
|
||||
| `GET` | `/api/preferences` | Return the current user's durable UI preferences. |
|
||||
@@ -241,13 +248,32 @@ header. Command failures are returned as HTTP 400 JSON responses with an
|
||||
|
||||
[`public/app.js`](public/app.js) implements a framework-free client. It:
|
||||
|
||||
- fetches a full state snapshot once per second;
|
||||
- polls status once per second, receiving tracks only when the playlist version changes;
|
||||
- temporarily suppresses polling while a browser-initiated command is active;
|
||||
- immediately renders the state returned by successful commands;
|
||||
- renders library navigation, playlists, tabs, transport status, and output
|
||||
selection;
|
||||
- implements keyboard actions and playlist drag-and-drop in the browser.
|
||||
|
||||
[`public/playlist-library.js`](public/playlist-library.js) renders the library's
|
||||
Folders/Playlists tabs and saved playlist summaries. `playlist-save` adds an
|
||||
open tab to the library by UUID. `playlist-open` reveals its own tab, reusing an
|
||||
already open tab, and `playlist-play` also starts playback. Neither action copies
|
||||
tracks into an unrelated tab. Only summary metadata is sent in `savedPlaylists`.
|
||||
|
||||
[`public/player-state.js`](public/player-state.js) keeps the active track array
|
||||
in memory and queues state, command and discovery requests. Each request sends
|
||||
the last received `playlistVersion` as a query parameter. A matching response
|
||||
contains `tracks: null`; the client supplies its cached tracks to the renderers.
|
||||
Requests without a version still receive the full list. Queueing prevents
|
||||
responses from being applied out of order.
|
||||
|
||||
The player caches track JSON, count, duration and an opaque version per tab.
|
||||
`save-current-tab!` invalidates this snapshot when the track list changes.
|
||||
Renaming a tab leaves its track snapshot intact. Versions are unique across
|
||||
tabs, users and server restarts. `renderPlaylist` uses the version to decide
|
||||
when to rebuild rows instead of comparing all track metadata on every poll.
|
||||
|
||||
[`public/translate.js`](public/translate.js) follows the key-based translation
|
||||
model used by rktplayer. It supports Dutch, English, German, French, Spanish,
|
||||
Italian, Swedish, Norwegian, Finnish and Icelandic with English fallback.
|
||||
@@ -314,9 +340,9 @@ sequenceDiagram
|
||||
participant D as DLNA renderer
|
||||
|
||||
loop Browser state polling
|
||||
B->>H: GET /api/state
|
||||
B->>H: GET /api/state?playlistVersion=known-version
|
||||
H->>P: player-state->jsexpr
|
||||
P-->>H: Full state snapshot
|
||||
P-->>H: State and version; tracks only if changed
|
||||
H-->>B: JSON response
|
||||
end
|
||||
|
||||
@@ -429,8 +455,9 @@ The main extension points are:
|
||||
- **Per-user pipelines, shared outputs:** playlist and transport state are
|
||||
isolated by username. Distinct outputs run concurrently; selecting an
|
||||
occupied output explicitly stops its previous owner and transfers it.
|
||||
- **Full-state snapshots:** a small and predictable client protocol, at the cost
|
||||
of repeatedly transferring all tracks and browser entries.
|
||||
- **Versioned playlists:** cached tracks are transferred only when the selected
|
||||
playlist version changes. Other status fields, including browser entries,
|
||||
remain part of each response.
|
||||
- **One-second polling:** robust and dependency-free, but introduces periodic
|
||||
traffic and up to one second of display latency.
|
||||
- **Lazy filesystem and backend initialization:** fast startup and low idle
|
||||
|
||||
Reference in New Issue
Block a user