diff web/fade/Light9FadeUi.ts @ 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/fade/Light9FadeUi.ts@06bf6dae8e64
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/fade/Light9FadeUi.ts	Sun May 12 19:02:10 2024 -0700
@@ -0,0 +1,169 @@
+import debug from "debug";
+import { css, html, LitElement, TemplateResult } from "lit";
+import { customElement, property } from "lit/decorators.js";
+import * as N3 from "n3";
+import { NamedNode, Quad } from "n3";
+import { Patch } from "../patch";
+import { getTopGraph } from "../RdfdbSyncedGraph";
+import { showRoot } from "../show_specific";
+import { SyncedGraph } from "../SyncedGraph";
+export { EditChoice } from "../EditChoice";
+export { Light9EffectFader } from "./Light9EffectFader";
+export { Light9Fader } from "./Light9Fader";
+
+debug.enable("*,autodep");
+const log = debug("fade");
+
+class FaderConfig {
+  constructor(public uri: NamedNode, public column: number) { }
+}
+
+class FadePage {
+  constructor(public uri: NamedNode) { }
+  faderConfigs: FaderConfig[] = [];
+}
+class FadePages {
+  pages: FadePage[] = [];
+}
+
+@customElement("light9-fade-ui")
+export class Light9FadeUi extends LitElement {
+  static styles = [
+    css`
+      :host {
+        display: block;
+        user-select: none; /* really this is only desirable during slider drag events */
+      }
+      .mappedToHw {
+        background: #393945;
+      }
+      #gm light9-fader {
+        width: 300px;
+      }
+    `,
+  ];
+  render() {
+    return html`
+      <rdfdb-synced-graph></rdfdb-synced-graph>
+
+      <h1>Fade</h1>
+<div id="gm">
+  <light9-fader .value=${this.grandMaster} @change=${this.gmChanged}></light9-fader>grand master
+</div>
+      ${(this.fadePages?.pages || []).map(this.renderPage.bind(this))}
+
+      <div><button @click=${this.addPage}>Add new page</button></div>
+    `;
+  }
+  private renderPage(page: FadePage): TemplateResult {
+    const mappedToHw = this.currentHwPage !== undefined && page.uri.equals(this.currentHwPage);
+    return html`<div class="${mappedToHw ? "mappedToHw" : ""}">
+      <fieldset>
+        <legend>
+          Page
+          <resource-display rename .uri=${page.uri}></resource-display>
+          ${mappedToHw ? html`mapped to hardware sliders` : html`
+          <button @click=${(ev: Event) => this.mapThisToHw(page.uri)}>Map this to hw</button>
+          `}
+        </legend>
+        ${page.faderConfigs.map((fd) => html` <light9-effect-fader .uri=${fd.uri}></light9-effect-fader> `)}
+      </fieldset>
+    </div>`;
+  }
+
+  graph!: SyncedGraph;
+  ctx: NamedNode = new NamedNode(showRoot + "/fade");
+
+  @property() fadePages?: FadePages;
+  @property() currentHwPage?: NamedNode;
+  @property() grandMaster?: number;
+
+  constructor() {
+    super();
+    getTopGraph().then((g) => {
+      this.graph = g;
+      this.graph.runHandler(this.compile.bind(this), `faders layout`);
+      this.graph.runHandler(this.compileGm.bind(this), `faders gm`);
+    });
+  }
+  connectedCallback(): void {
+    super.connectedCallback();
+  }
+
+  compile() {
+    const U = this.graph.U();
+    this.fadePages = undefined;
+    const fadePages = new FadePages();
+    for (let page of this.graph.subjects(U("rdf:type"), U(":FadePage"))) {
+      const fp = new FadePage(page as NamedNode);
+      try {
+        for (let fader of this.graph.objects(page, U(":fader"))) {
+          const colLit = this.graph.stringValue(fader, U(':column'))
+          fp.faderConfigs.push(new FaderConfig(fader as NamedNode, parseFloat(colLit)));
+        }
+        fp.faderConfigs.sort((a, b) => {
+          return a.column - (b.column);
+        });
+        fadePages.pages.push(fp);
+      } catch (e) { }
+    }
+    fadePages.pages.sort((a, b) => {
+      return a.uri.value.localeCompare(b.uri.value);
+    });
+    this.fadePages = fadePages;
+    this.currentHwPage = undefined;
+    try {
+      const mc = this.graph.uriValue(U(":midiControl"), U(":map"));
+      this.currentHwPage = this.graph.uriValue(mc, U(":outputs"));
+    } catch (e) { }
+  }
+  compileGm() {
+    const U = this.graph.U();
+    this.grandMaster = undefined
+    let newVal
+    try {
+
+      newVal = this.graph.floatValue(U(':grandMaster'), U(':value'))
+    } catch (e) {
+      return
+    }
+    this.grandMaster = newVal;
+
+  }
+  gmChanged(ev: CustomEvent) {
+    const U = this.graph.U();
+    const newVal = ev.detail.value
+    // this.grandMaster = newVal;
+    this.graph.patchObject(U(':grandMaster'), U(':value'), this.graph.LiteralRoundedFloat(newVal), this.ctx)
+
+  }
+
+
+  mapThisToHw(page: NamedNode) {
+    const U = this.graph.U();
+    log("map to hw", page);
+    const mc = this.graph.uriValue(U(":midiControl"), U(":map"));
+    this.graph.patchObject(mc, U(":outputs"), page, this.ctx);
+  }
+
+  addPage() {
+    const U = this.graph.U();
+    const uri = this.graph.nextNumberedResource(showRoot + "/fadePage");
+    const adds = [
+      //
+      new Quad(uri, U("rdf:type"), U(":FadePage"), this.ctx),
+      new Quad(uri, U("rdfs:label"), N3.DataFactory.literal("unnamed"), this.ctx),
+    ];
+    for (let n = 1; n <= 8; n++) {
+      const f = this.graph.nextNumberedResource(showRoot + "/fader");
+      const s = this.graph.nextNumberedResource(showRoot + "/faderset");
+      adds.push(new Quad(uri, U(":fader"), f, this.ctx));
+      adds.push(new Quad(f, U("rdf:type"), U(":Fader"), this.ctx));
+      adds.push(new Quad(f, U(":column"), N3.DataFactory.literal("" + n), this.ctx));
+      adds.push(new Quad(f, U(":setting"), s, this.ctx));
+      adds.push(new Quad(s, U(":effectAttr"), U(":strength"), this.ctx));
+      adds.push(new Quad(s, U(":value"), this.graph.LiteralRoundedFloat(0), this.ctx));
+    }
+    this.graph.applyAndSendPatch(new Patch([], adds));
+  }
+}