diff options
Diffstat (limited to 'docs/MESHBAY_DESIGN.md')
| -rw-r--r-- | docs/MESHBAY_DESIGN.md | 54 |
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 |