aboutsummaryrefslogtreecommitdiffstats
path: root/docs/MESHBAY_DESIGN.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/MESHBAY_DESIGN.md')
-rw-r--r--docs/MESHBAY_DESIGN.md54
1 files changed, 38 insertions, 16 deletions
diff --git a/docs/MESHBAY_DESIGN.md b/docs/MESHBAY_DESIGN.md
index 64364b0..5d33f5f 100644
--- a/docs/MESHBAY_DESIGN.md
+++ b/docs/MESHBAY_DESIGN.md
@@ -3423,27 +3423,49 @@ pauses the local element too, which otherwise goes on fetching for nobody. The
copy-URL cast has no receiver to read and keeps the ordinary player.
**A television is chosen for the session, not for one film**
-(`cast-session.js`). Any cast button — Videos' toolbar, the Photos toolbar, a
-photo album's bar, the lightbox, the player — sets it, and it is held in memory
-only. A film opened
+(`cast-session.js`). Any cast button — Videos', Photos' and Music's toolbars, a
+photo album's bar, the lightbox, the video player, the music bar — sets it, and
+it is held in memory only. A film opened
while one is set starts its cast as a restart does: pending until the first
segment, then the relay and `connect` (or `reload`, when the receiver is already
connected), with the player drawn as the remote from the start. *Stop casting*
clears it, from the player's remote or from any button.
-**A photo is served at `/image`, one at a time** (`cast:image`). The page scales
-it to fit 1920×1080, applies its EXIF orientation and re-encodes it as JPEG
-before it leaves: a camera original is too large for a receiver to decode in good
-time, and some formats it does not decode at all. The relay starts for it if
-nothing else has, serves it behind the stream's token with a versioned address
-(a receiver handed the same URL twice shows what it already has), and accepts
-only `image/jpeg`, `image/png` or `image/webp`. **The shell, not the page, says
-what the receiver loads:** the relay's photo URL is loaded as a picture
-(`streamType: NONE`, photo metadata, no subtitles), any other relay URL as the
-stream, and on Android no URL but the relay's own is accepted at all. A photo
-does not start the foreground service, and its load answers as soon as the
-receiver accepts it: a photo never reaches PLAYING. Only the newest photo asked
-for is sent; paging quickly shows where the reader stopped.
+**A photo or a music track is served whole at `/file`, one at a time**
+(`cast:file:begin`, `:write`, `:end`), its cover at `/cover`. It crosses in
+pieces — binary frames of a megabyte on Android — because a lossless track is
+too large for one bridge message, and on Android it is written to the relay's
+spool directory rather than held. The relay starts for it if nothing else has,
+serves it behind the stream's token with a versioned address (a receiver handed
+the same URL twice shows what it already has), honours byte ranges (a receiver
+seeks in a track that way), and accepts only pictures and the audio types the
+music player plays. **The shell, not the page, says what the receiver loads:**
+the relay's file is loaded as what the relay was told it is — a photo as a
+picture (`streamType: NONE`), a track as music (`BUFFERED`, with title, artist,
+album and the relay's cover URL), at `startAt` seconds for a track picked up
+mid-song — any other relay URL as the stream, and on Android no URL but the
+relay's own is accepted at all. A file does not start the foreground service; a
+photo's load answers as soon as the receiver accepts it, since a photo never
+reaches PLAYING.
+
+**A photo is scaled before it leaves.** The page fits it to 1920×1080, applies
+its EXIF orientation and re-encodes it as JPEG: a camera original is too large
+for a receiver to decode in good time, and some formats it does not decode at
+all. Only the newest photo asked for is sent; paging quickly shows where the
+reader stopped.
+
+**With a television chosen, the music bar is its remote.** Each track, once
+decrypted, goes to the relay with its cover instead of to the `<audio>`
+element, which keeps the source for its duration only. Play, pause, seek
+(`cast:chromecast:seek`) and previous drive the receiver; the bar's clock is the
+receiver's, polled once a second; and the receiver's IDLE/FINISHED moves the
+queue on as `ended` does, once per track, because the receiver keeps reporting
+it until it is given something else. The session records which view the
+television is showing (`castSession.owner`): a film or a photo opened meanwhile
+takes it, the bar pauses and stops reading the receiver, and play gives it the
+track back from where it was. A television chosen mid-track picks the track up
+where it was; *Stop casting* carries it on locally from where the television
+was.
**The interface itself is not cast.** The default media receiver plays what it
is given and renders nothing of its own, and a rendered interface sent to it as