Mercurial > code > home > repos > light9
diff web/light9-vidref-replay-stack.js @ 2376:4556eebe5d73
topdir reorgs; let pdm have its src/ dir; separate vite area from light9/
author | drewp@bigasterisk.com |
---|---|
date | Sun, 12 May 2024 19:02:10 -0700 |
parents | light9/web/light9-vidref-replay-stack.js@286a34d9ccba |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/light9-vidref-replay-stack.js Sun May 12 19:02:10 2024 -0700 @@ -0,0 +1,183 @@ +import { LitElement, TemplateResult, html, css } from '/node_modules/lit-element/lit-element.js'; +import debug from '/lib/debug/debug-build-es6.js'; +import _ from '/lib/underscore/underscore-min-es6.js'; +import { rounding } from '/node_modules/significant-rounding/index.js'; + +const log = debug('stack'); + +class Light9VidrefReplayStack extends LitElement { + + static get properties() { + return { + songTime: { type: Number, attribute: false }, // from musicState.t but higher res + musicState: { type: Object, attribute: false }, + players: { type: Array, attribute: false }, + size: { type: String, attribute: true } + }; + } + + constructor() { + super(); + this.musicState = {}; + } + + setVideoTimesFromSongTime() { + this.shadowRoot.querySelectorAll('light9-vidref-replay').forEach( + (r) => { + r.setVideoTimeFromSongTime(this.songTime, this.musicState.playing); + }); + } + nudgeTime(dt) { + this.songTime += dt; + log('song now', this.songTime); + } + fineTime() { + if (this.musicState.playing) { + const sinceLastUpdate = (Date.now() - this.musicState.reportTime) / 1000; + this.songTime = sinceLastUpdate + this.musicState.tStart; + } else if (this.lastFineTimePlayingState) { + this.songTime = this.musicState.t; + } + this.lastFineTimePlayingState = this.musicState.playing; + requestAnimationFrame(this.fineTime.bind(this)); + } + + updated(changedProperties) { + if (changedProperties.has('songTime')) { + this.setVideoTimesFromSongTime(); + } + } + + firstUpdated() { + this.songTimeRangeInput = this.shadowRoot.querySelector('#songTime'); + + const ws = reconnectingWebSocket('../ascoltami/time/stream', + this.receivedSongAndTime.bind(this)); + reconnectingWebSocket('../vidref/time/stream', this.receivedRemoteScrubbedTime.bind(this)); + // bug: upon connecting, clear this.song + this.fineTime(); + } + + receivedSongAndTime(msg) { + this.musicState = msg; + this.musicState.reportTime = Date.now(); + this.musicState.tStart = this.musicState.t; + + this.songTimeRangeInput.max = this.musicState.duration; + + if (this.musicState.song != this.song) { + this.song = this.musicState.song; + this.getReplayMapForSong(this.song); + } + } + + receivedRemoteScrubbedTime(msg) { + this.songTime = msg.st; + + // This doesn't work completely since it will keep getting + // updates from ascoltami slow updates. + if (msg.song != this.song) { + this.song = msg.song; + this.getReplayMapForSong(this.song); + } + } + + getReplayMapForSong(song) { + const u = new URL(window.location.href); + u.pathname = '/vidref/replayMap' + u.searchParams.set('song', song); + u.searchParams.set('maxClips', this.size == "small" ? '1' : '3'); + fetch(u.toString()).then((resp) => { + if (resp.ok) { + resp.json().then((msg) => { + this.players = msg.map(this.makeClipRow.bind(this)); + this.updateComplete.then(this.setupClipRows.bind(this, msg)); + }); + } + }); + } + + setupClipRows(msg) { + const nodes = this.shadowRoot.querySelectorAll('light9-vidref-replay'); + nodes.forEach((node, i) => { + node.uri = msg[i].uri; + node.videoUrl = msg[i].videoUrl; + node.songToVideo = msg[i].songToVideo; + }); + this.setVideoTimesFromSongTime(); + } + + makeClipRow(clip) { + return html`<light9-vidref-replay @clips-changed="${this.onClipsChanged}" size="${this.size}"></light9-vidref-replay>`; + } + + onClipsChanged(ev) { + this.getReplayMapForSong(this.song); + } + + disconnectedCallback() { + log('bye'); + //close socket + } + + userMovedSongTime(ev) { + const st = this.songTimeRangeInput.valueAsNumber; + this.songTime = st; + + fetch('/ascoltami/seekPlayOrPause', { + method: 'POST', + body: JSON.stringify({scrub: st}), + }); + } + + static get styles() { + return css` + :host { + display: inline-block; + } + #songTime { + width: 100%; + } + #clips { + display: flex; + flex-direction: column; + } + a { + color: rgb(97, 97, 255); + } + #songTime { + font-size: 27px; + } + light9-vidref-replay { + margin: 5px; + } + `; + } + + render() { + const songTimeRange = this.size != "small" ? html`<input id="songTime" type="range" + .value="${this.songTime}" + @input="${this.userMovedSongTime}" + min="0" max="0" step=".001"></div> + <div><a href="${this.musicState.song}">${this.musicState.song}</a></div>` : ''; + + + const globalCommands = this.size != 'small' ? html` + <div> + <button @click="${this.onClipsChanged}">Refresh clips for song</button> + </div> +` : ''; + return html` + <div> + ${songTimeRange} + <div id="songTime">showing song time ${rounding(this.songTime, 3)}</div> + <div>clips:</div> + <div id="clips"> + ${this.players} + </div> + ${globalCommands} +`; + + } +} +customElements.define('light9-vidref-replay-stack', Light9VidrefReplayStack);