diff --git a/light9/ascoltami/Light9AscoltamiUi.ts b/light9/ascoltami/Light9AscoltamiUi.ts --- a/light9/ascoltami/Light9AscoltamiUi.ts +++ b/light9/ascoltami/Light9AscoltamiUi.ts @@ -1,5 +1,5 @@ import debug from "debug"; -import { html, LitElement } from "lit"; +import { css, html, LitElement } from "lit"; import { customElement, property } from "lit/decorators.js"; import { NamedNode } from "n3"; import { getTopGraph } from "../web/RdfdbSyncedGraph"; @@ -8,6 +8,7 @@ export { RdfdbSyncedGraph } from "../web export { Light9TimelineAudio } from "../web/light9-timeline-audio"; import { classMap } from "lit/directives/class-map.js"; import { TimingUpdate } from "./main"; +import { Zoom } from "../web/light9-timeline-audio"; debug.enable("*"); const log = debug("asco"); @@ -28,9 +29,22 @@ export class Light9AscoltamiUi extends L times!: { intro: number; post: number }; @property() nextText: string = ""; @property() isPlaying: boolean = false; + @property() show: NamedNode | null = null; @property() song: NamedNode | null = null; @property() t: number = 0; @property() currentDuration: number = 0; + @property() zoom: Zoom; + @property() overviewZoom: Zoom; + static styles = [ + css` + .timeRow { + margin: 14px; + } + light9-timeline-audio { + height: 80px; + } + `, + ]; render() { return html` @@ -38,6 +52,12 @@ export class Light9AscoltamiUi extends L

ascoltami [metrics]

+
+
+ + +
+

diff --git a/light9/ascoltami/webapp.py b/light9/ascoltami/webapp.py --- a/light9/ascoltami/webapp.py +++ b/light9/ascoltami/webapp.py @@ -10,7 +10,7 @@ import cyclone.websocket from cycloneerr import PrettyErrorHandler from light9.metrics import metricsRoute from light9.namespaces import L9 -from light9.showconfig import getSongsFromShow, songOnDisk +from light9.showconfig import getSongsFromShow, showUri, songOnDisk from rdflib import URIRef from twisted.internet import reactor from twisted.internet.interfaces import IReactorTime @@ -36,6 +36,7 @@ class config(cyclone.web.RequestHandler) self.write( json.dumps(dict( host=socket.gethostname(), + show=str(showUri()), times={ # these are just for the web display. True values are on Player.__init__ 'intro': 4, diff --git a/light9/web/light9-timeline-audio.ts b/light9/web/light9-timeline-audio.ts --- a/light9/web/light9-timeline-audio.ts +++ b/light9/web/light9-timeline-audio.ts @@ -1,13 +1,34 @@ import { debug } from "debug"; -import { css, html, LitElement, TemplateResult } from "lit"; -import { customElement, property } from "lit/decorators.js"; +import { css, html, LitElement, PropertyValues, TemplateResult } from "lit"; +import { customElement, property, state } from "lit/decorators.js"; +import { NamedNode } from "n3"; +import { loadConfigFromFile } from "vite"; +import { getTopGraph } from "./RdfdbSyncedGraph"; +import { SyncedGraph } from "./SyncedGraph"; const log = debug("audio"); +export interface Zoom { + duration: number | null; + t1: number; + t2: number; +} + +function nodeHasChanged(newVal?: NamedNode, oldVal?: NamedNode): boolean { + if (newVal === undefined && oldVal === undefined) { + return false; + } + if (newVal === undefined || oldVal === undefined) { + return true; + } + return !newVal.equals(oldVal); +} + // (potentially-zoomed) spectrogram view @customElement("light9-timeline-audio") export class Light9TimelineAudio extends LitElement { + graph!: SyncedGraph; render() { return html`
- +
`; } - // properties= { - // graph: {type: Object, notify: true}, - // show: {type: String, notify: true}, - // song: {type: String, notify: true}, - // zoom: {type: Object, notify: true}, - // imgSrc: { type: String, notify: true}, - // imgWidth: { computed: '_imgWidth(zoom)' }, - // imgLeft: { computed: '_imgLeft(zoom)' }, - // } - // observers= [ - // 'setImgSrc(graph, show, song)' - // ] - ready() { - this.zoom = { duration: 0 }; + @property({ hasChanged: nodeHasChanged }) show!: NamedNode; + @property({ hasChanged: nodeHasChanged }) song!: NamedNode; + @property() zoom: Zoom = { duration: null, t1: 0, t2: 1 }; + @state() imgSrc: string = "#"; + @state() imgWidth: string = "0"; // css + @state() imgLeft: string = "0"; // css + + constructor() { + super(); + + getTopGraph().then((g) => { + this.graph = g; + }); } + + updated(changedProperties: PropertyValues) { + if (changedProperties.has("song") || changedProperties.has("show")) { + if (this.song && this.show) { + this.graph.runHandler(this.setImgSrc.bind(this), "timeline-audio " + this.song); + } + } + if (changedProperties.has("zoom")) { + this.imgWidth = this._imgWidth(this.zoom); + this.imgLeft = this._imgLeft(this.zoom); + } + } + setImgSrc() { - graph.runHandler( - function () { - try { - var root = this.graph.stringValue(this.graph.Uri(this.show), this.graph.Uri(":spectrogramUrlRoot")); - } catch (e) { - return; - } + try { + var root = this.graph.stringValue(this.show, this.graph.Uri(":spectrogramUrlRoot")); + } catch (e) { + return; + } - try { - var filename = this.graph.stringValue(this.song, this.graph.Uri(":songFilename")); - } catch (e) { - return; - } + try { + var filename = this.graph.stringValue(this.song, this.graph.Uri(":songFilename")); + } catch (e) { + return; + } - this.imgSrc = root + "/" + filename.replace(".wav", ".png").replace(".ogg", ".png"); - }.bind(this), - "timeline-audio " + this.song - ); + this.imgSrc = root + "/" + filename.replace(".wav", ".png").replace(".ogg", ".png"); + log(`imgSrc ${this.imgSrc}`); } - _imgWidth(zoom) { + + _imgWidth(zoom: Zoom): string { if (!zoom.duration) { return "100%"; } return 100 / ((zoom.t2 - zoom.t1) / zoom.duration) + "%"; } - _imgLeft(zoom) { + _imgLeft(zoom: Zoom): string { if (!zoom.duration) { return "0"; } diff --git a/light9/web/style.css b/light9/web/style.css --- a/light9/web/style.css +++ b/light9/web/style.css @@ -98,9 +98,6 @@ div.keys { background: #a90707; } -.timeRow { - margin: 14px; -} .stalled { opacity: 0.5;