diff options
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/video-player.js')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/video-player.js | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/video-player.js b/packages/meshbay-hub/src/meshbay_hub/static/video-player.js index 2c424fb..37ea727 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/video-player.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/video-player.js @@ -6,6 +6,7 @@ import { Icon } from './icon.js'; import { formatSize, CHUNK_SIZE, pipelinedDownload } from './file-utils.js'; import { loadAuth } from './hub-client.js'; import * as platform from './platform.js'; +import { castSession } from './cast-session.js'; // Seconds of already-watched video kept in the SourceBuffer, and the queue depth // past which we start making room before being forced to. @@ -484,17 +485,22 @@ function VideoPlayer({ entry, transportRef, gekRef, onClose, onDownload }) { // Where the stream the node is sending begins, in film time. The same number // the SourceBuffer gets as its `timestampOffset`. const streamStartRef = useRef(0); - const [castActive, setCastActive] = useState(false); + // A television already chosen this session (cast-session.js) takes the film + // from its first segment: the cast starts as a restart would, pending until + // the init segment arrives, and the player opens as its remote. Read once — + // a television chosen while this film plays is chosen here, by the picker. + const [autoCast] = useState(() => (castSession.supported ? castSession.device : null)); + const [castActive, setCastActive] = useState(Boolean(autoCast)); const [castUrl, setCastUrl] = useState(null); const [castPickerOpen, setCastPickerOpen] = useState(false); const [castDevices, setCastDevices] = useState([]); const [castScanning, setCastScanning] = useState(false); - const [castDeviceName, setCastDeviceName] = useState(null); - const castActiveRef = useRef(false); + const [castDeviceName, setCastDeviceName] = useState(autoCast ? autoCast.name : null); + const castActiveRef = useRef(Boolean(autoCast)); const castCodecRef = useRef(null); const initSegmentRef = useRef(null); - const castRestartPendingRef = useRef(false); - const castDeviceRef = useRef(null); + const castRestartPendingRef = useRef(Boolean(autoCast)); + const castDeviceRef = useRef(autoCast); const castRestartGenRef = useRef(0); // The receiver as last polled: { playerState, position } with the position // on the film's timeline, or null before it has answered. @@ -1310,6 +1316,7 @@ function VideoPlayer({ entry, transportRef, gekRef, onClose, onDownload }) { }).then(async (result) => { if (castRestartGenRef.current !== gen) return; if (!result) return; + if (device || castSession.device) castSession.claim('video'); setCastUrl(result.url); const status = await platform.cast.status(); if (status && status.chromecast && status.chromecast.connected) { @@ -1758,7 +1765,10 @@ function VideoPlayer({ entry, transportRef, gekRef, onClose, onDownload }) { return () => { stopped = true; clearInterval(id); }; }, [remoteMode]); + // Stopping here is stopping for the session: the next film or photo stays + // on this device until a television is chosen again. const stopCast = async () => { + castSession.forget(); await platform.cast.chromecastDisconnect().catch(() => {}); await platform.cast.stop(); setCastActive(false); castActiveRef.current = false; @@ -1896,6 +1906,7 @@ function VideoPlayer({ entry, transportRef, gekRef, onClose, onDownload }) { ${castDevices.map(d => html` <button class="cast-picker-item" onClick=${() => { setCastPickerOpen(false); + castSession.choose(d); setCastDeviceName(d.name); setCastActive(true); castActiveRef.current = true; castRestartPendingRef.current = true; |