Link video/music playback to the OS's own media controls (Windows SMTC, macOS Now Playing, ...) #22
Loading…
Reference in a new issue
No description provided.
Delete branch "feature/media-session-integration"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Asked for directly: link whatever's playing to Windows' own media popup. Implemented via the standard Media Session API (
navigator.mediaSession), which the same code also surfaces to macOS' Now Playing widget and Android's notification for free, on whichever browser implements it (Chromium family — Firefox never has).mediaSession.ts: a thin wrapper (every export is a one-line feature-detection guard around the real browser call), shared byviews/player/Player.ts(video) andmusicBar/MusicBar.ts(music) — the two can never both be active at once, so there's no risk of them fighting over this single global.updatePlayPauseBtn/updateProgressBarin Player.ts,setPlayIcon/updatePositionDisplayin MusicBar.ts) rather than adding parallel call sites.requestPause/requestResumethe in-page request toolbar already uses (now factored out so both can call them); seeking is gated onisHostthe same way the in-page seek bar already is (factored into a sharedseekTo).nexttrackhandler is what makes the OS show that control at all, so its presence tracks whatever the in-page equivalent already tracks (isHost && hasNextQueuedfor video's#nextBtn,music.currentfor the vote-skip button — clicking the OS's own "next" for music casts one skip vote, same as the in-page button).clearMediaSession) on leaving a party/page; a lightersetMediaSessionIdle(metadata/state only) covers a listen party's queue running empty while the party itself stays open, since play/pause/seek stay meaningful the instant something plays again.Test plan
npm run typecheck(client) — cleannpm run build(client) — cleanmediaSession.tschecked directly against the real API in a real Chromium browser: metadata resolves to a genuineMediaMetadatawith the right fields and a resolved artwork URL, playback/position state apply without throwing, an invalid (non-positive/NaN) duration is silently skipped rather than reaching the call that would throw on it, action-handler registration doesn't throw with or withoutonSeek, and bothsetMediaSessionIdle/clearMediaSessioncorrectly reset metadata tonulland playback state to'none'.🤖 Generated with Claude Code