aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-client/src/main.js
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-10-05 02:29:27 +0200
committerChristophe Besson <cbesson@gmail.com>2026-10-05 02:29:27 +0200
commitee9798fe3b88face2fa34f14874770f509c788a5 (patch)
treef63e9506882863a885a907796eb977ec69137718 /packages/meshbay-client/src/main.js
parent243bcf017b4957237b3ddf556bd0a37296eb8798 (diff)
downloadmeshbay-ee9798fe3b88face2fa34f14874770f509c788a5.tar.gz
feat(cast): music on the TV, the music bar as its remote
A cast button in Music's toolbar and in the music bar. With a television chosen, each decrypted track goes to the relay with its cover — found as the album card finds it — and plays there as music with its title, artist and album; the bar's play, pause, seek, previous and next drive the receiver, its clock is the receiver's, and the end of a track there moves the queue on. A film or a photo taking the television pauses the bar; stopping the cast carries the track on locally. Photos and tracks now share one path: a whole file sent to the relay in pieces (binary frames on Android, written to disk there), served at /file with byte ranges and its cover at /cover, and loaded as what the relay says it is. cast:image is gone; cast:chromecast:seek is new. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-client/src/main.js')
-rw-r--r--packages/meshbay-client/src/main.js30
1 files changed, 16 insertions, 14 deletions
diff --git a/packages/meshbay-client/src/main.js b/packages/meshbay-client/src/main.js
index 1c371f5..a2a7a86 100644
--- a/packages/meshbay-client/src/main.js
+++ b/packages/meshbay-client/src/main.js
@@ -2333,29 +2333,31 @@ function registerBridge() {
handle('cast:devices', async () => castChromecast.devices());
- // One photo at a time, scaled and re-encoded by the page.
- handle('cast:image', async (_e, img) => {
- return castRelay.showImage({ bytes: Buffer.from(img.bytes), type: img.type });
- });
+ // A whole file for the receiver — a photo, a music track — in three steps,
+ // so that a large one never crosses in a single message.
+ handle('cast:file:begin', async (_e, f) => castRelay.beginFile(f || {}));
+ handle('cast:file:write', async (_e, data) => castRelay.writeFile(Buffer.from(data)));
+ handle('cast:file:end', async () => castRelay.endFile());
- // The relay's photo is loaded as a picture, anything else as the stream;
- // the page does not get to say which.
+ // The relay's file is loaded as what the relay says it is, anything else as
+ // the stream; the page does not get to say which.
const loadOf = (mediaUrl, subtitle) => (
- mediaUrl && mediaUrl === castRelay.imageUrl
- ? { subtitle: null, contentType: castRelay.imageType }
- : { subtitle: subtitle === undefined ? castRelay.subtitle : subtitle,
- contentType: 'video/mp4' });
+ mediaUrl && mediaUrl === castRelay.fileUrl
+ ? { subtitle: null, file: { contentType: castRelay.fileType, meta: castRelay.fileMeta } }
+ : { subtitle: subtitle === undefined ? castRelay.subtitle : subtitle, file: null });
- handle('cast:chromecast:connect', async (_e, { deviceId, mediaUrl, subtitle }) => {
+ handle('cast:chromecast:connect', async (_e, { deviceId, mediaUrl, subtitle, startAt }) => {
const l = loadOf(mediaUrl, subtitle);
- return castChromecast.connect(deviceId, mediaUrl, l.subtitle, l.contentType);
+ return castChromecast.connect(deviceId, mediaUrl, l.subtitle, l.file, l.file ? startAt : 0);
});
- handle('cast:chromecast:reload', async (_e, { mediaUrl, subtitle }) => {
+ handle('cast:chromecast:reload', async (_e, { mediaUrl, subtitle, startAt }) => {
const l = loadOf(mediaUrl, subtitle);
- return castChromecast.reload(mediaUrl, l.subtitle, l.contentType);
+ return castChromecast.reload(mediaUrl, l.subtitle, l.file, l.file ? startAt : 0);
});
+ handle('cast:chromecast:seek', async (_e, seconds) => castChromecast.seek(seconds));
+
// The player becomes a remote while casting: these drive the receiver.
handle('cast:chromecast:pause', async () => castChromecast.pause());
handle('cast:chromecast:play', async () => castChromecast.play());