changeset 2127:1dc96b97a544

two zoomed spectrogram views in asco
author drewp@bigasterisk.com
date Fri, 03 Jun 2022 00:41:13 -0700
parents 58389a24e222
children e2ed5ce36253
files light9/ascoltami/Light9AscoltamiUi.ts light9/ascoltami/index.html light9/ascoltami/webapp.py light9/web/light9-timeline-audio.ts light9/web/style.css
diffstat 5 files changed, 95 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- a/light9/ascoltami/Light9AscoltamiUi.ts	Thu Jun 02 23:35:47 2022 -0700
+++ b/light9/ascoltami/Light9AscoltamiUi.ts	Fri Jun 03 00:41:13 2022 -0700
@@ -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 { 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 @@
   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`<rdfdb-synced-graph></rdfdb-synced-graph>
 
@@ -38,6 +52,12 @@
 
       <h1>ascoltami <a href="metrics">[metrics]</a></h1>
 
+      <div class="timeRow">
+        <div id="timeSlider"></div>
+        <light9-timeline-audio .show=${this.show} .song=${this.song} .zoom=${this.overviewZoom}></light9-timeline-audio>
+        <light9-timeline-audio .show=${this.show} .song=${this.song} .zoom=${this.zoom}></light9-timeline-audio>
+      </div>
+
       <div class="commands">
         <button id="cmd-stop" @click=${this.onCmdStop} class="playMode ${classMap({ active: !this.isPlaying })}">
           <strong>Stop</strong>
@@ -106,13 +126,10 @@
     });
   }
 
-  currentDurationChanged(newDuration: number): void {
-    this.currentDuration = newDuration;
-  }
-
   async musicSetup() {
     // shoveled over from the vanillajs version
     const config = await (await fetch("api/config")).json();
+    this.show = new NamedNode(config.show);
     this.times = config.times;
     document.title = document.title.replace("{{host}}", config.host);
     const h1 = document.querySelector("h1")!;
@@ -130,14 +147,16 @@
       this.nextText = data.next;
       this.isPlaying = data.playing;
       this.currentDuration = data.duration;
+      this.song = new NamedNode(data.song);
+      this.overviewZoom = { duration: data.duration, t1: 0, t2: data.duration };
+      this.zoom = { duration: data.duration, t1: data.t - 2, t2: data.t + 20 };
     });
   }
 
   constructor() {
     super();
     this.bindKeys();
-    //   byId("cmd-stop").addEventListener("click", (ev: Event) =>
-    // );
+    this.zoom = this.overviewZoom = { duration: null, t1: 0, t2: 1 };
 
     getTopGraph().then((g) => {
       this.graph = g;
--- a/light9/ascoltami/index.html	Thu Jun 02 23:35:47 2022 -0700
+++ b/light9/ascoltami/index.html	Fri Jun 03 00:41:13 2022 -0700
@@ -36,9 +36,6 @@
         </tr>
       </table>
 
-      <div class="timeRow">
-        <div id="timeSlider"></div>
-      </div>
     </div>
 
     <hr />
--- a/light9/ascoltami/webapp.py	Thu Jun 02 23:35:47 2022 -0700
+++ b/light9/ascoltami/webapp.py	Fri Jun 03 00:41:13 2022 -0700
@@ -10,7 +10,7 @@
 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 @@
         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,
--- a/light9/web/light9-timeline-audio.ts	Thu Jun 02 23:35:47 2022 -0700
+++ b/light9/web/light9-timeline-audio.ts	Fri Jun 03 00:41:13 2022 -0700
@@ -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`
       <style>
@@ -25,56 +46,67 @@
         img {
           height: 100%;
           position: relative;
+          transition: left .1s linear;
+
         }
       </style>
       <div>
-        <img src="{{imgSrc}}" style="width: {{imgWidth}} ; left: {{imgLeft}}" />
+        <img src=${this.imgSrc} style="width: ${this.imgWidth}; left: ${this.imgLeft}" />
       </div>
     `;
   }
-  //    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";
     }
--- a/light9/web/style.css	Thu Jun 02 23:35:47 2022 -0700
+++ b/light9/web/style.css	Fri Jun 03 00:41:13 2022 -0700
@@ -98,9 +98,6 @@
   background: #a90707;
 }
 
-.timeRow {
-  margin: 14px;
-}
 
 .stalled {
   opacity: 0.5;