Files @ 2ce77421c0b7
Branch filter:

Location: light9/web/light9-timeline-audio.ts - annotation

drewp@bigasterisk.com
put a big time display on ascoltami
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
06da5db2fafe
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
e7e03c203c99
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
06da5db2fafe
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
06da5db2fafe
06da5db2fafe
4556eebe5d73
06da5db2fafe
4556eebe5d73
06da5db2fafe
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
import { debug } from "debug";
import { html, LitElement, PropertyValues } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { NamedNode } from "n3";
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;
  graphReady: Promise<void>;
  render() {
    return html`
      <style>
        :host {
          display: block;
          /* shouldn't be seen, but black is correct for 'no
         audio'. Maybe loading stripes would be better */
          background: #202322;
          outline: 1px solid #333;
        }
        div {
          width: 100%;
          height: 100%;
          overflow: hidden;
        }
        img {
          height: 100%;
          position: relative;
          transition: left 0.1s linear;
        }
      </style>
      <div>
        <img src=${this.imgSrc} style="width: ${this.imgWidth}; left: ${this.imgLeft}" />
      </div>
    `;
  }
  @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();

    this.graphReady = getTopGraph().then((g) => {
      this.graph = g;
    });
  }

  async updated(changedProperties: PropertyValues) {
    super.updated(changedProperties);
    if (changedProperties.has("song") || changedProperties.has("show")) {
      await this.graphReady;
      if (this.song && this.show) {
        this.graph.runHandler(this.setImgSrc.bind(this), "timeline-audio " + this.song.value);
      }
    }
    if (changedProperties.has("zoom")) {
      this.imgWidth = this._imgWidth(this.zoom);
      this.imgLeft = this._imgLeft(this.zoom);
    }
  }

  setImgSrc() {
    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;
    }

    this.imgSrc = root + "/" + filename.replace(".wav", ".png").replace(".ogg", ".png");
    log(`imgSrc ${this.imgSrc}`);
  }

  _imgWidth(zoom: Zoom): string {
    if (!zoom.duration) {
      return "100%";
    }

    return 100 / ((zoom.t2 - zoom.t1) / zoom.duration) + "%";
  }
  _imgLeft(zoom: Zoom): string {
    if (!zoom.duration) {
      return "0";
    }

    var percentPerSec = 100 / (zoom.t2 - zoom.t1);
    return -percentPerSec * zoom.t1 + "%";
  }
}