Files
AV-Live/web_realart/public/control/js/transport.js
T
L'électron rare d058858b23
CI build oscope-of / build-check (push) Has been cancelled
feat(web): tempo -/+ stepper buttons
One-BPM steps beside the tempo slider (fine adjustment is hard on a
touch slider mid-performance) plus a live numeric readout; both paths
share the same /launch/tempo send.
2026-07-02 22:38:16 +02:00

57 lines
2.0 KiB
JavaScript

// js/transport.js — beat/rms feedback + tempo, filter, quantise controls.
import { send, on } from "./osc.js";
let beatFlashTimer = null;
export function init() {
// /sync/beat — flash beat dot for 80 ms
on("/sync/beat", () => {
const beatDot = document.getElementById("beat-dot");
if (!beatDot) return;
if (beatFlashTimer !== null) { clearTimeout(beatFlashTimer); beatFlashTimer = null; }
beatDot.classList.add("flash");
beatFlashTimer = setTimeout(() => {
beatDot.classList.remove("flash");
beatFlashTimer = null;
}, 80);
});
// /sync/rms — drive master VU meter width
on("/sync/rms", (args) => {
const raw = Number(args[0]);
const rms = Number.isFinite(raw) ? Math.max(0, Math.min(1, raw)) : 0;
const bar = document.getElementById("vu-bar");
if (bar) bar.style.width = `${rms * 100}%`;
});
// Tempo: slider + -/+ steppers (1 BPM per click), value label kept in sync
const tempo = document.getElementById("tempo");
const tempoVal = document.getElementById("tempo-val");
const pushTempo = () => {
if (tempoVal) tempoVal.textContent = tempo.value;
send("/launch/tempo", +tempo.value);
};
tempo && tempo.addEventListener("input", pushTempo);
const stepTempo = (d) => {
if (!tempo) return;
tempo.value = Math.max(+tempo.min, Math.min(+tempo.max, +tempo.value + d));
pushTempo();
};
const tMinus = document.getElementById("tempo-minus");
const tPlus = document.getElementById("tempo-plus");
tMinus && tMinus.addEventListener("click", () => stepTempo(-1));
tPlus && tPlus.addEventListener("click", () => stepTempo(1));
// Filter
const filt = document.getElementById("filter");
filt && filt.addEventListener("input", () => send("/control/fx/filter", +filt.value));
// Quantize selector
document.querySelectorAll(".quant-btn").forEach(btn =>
btn.addEventListener("click", () => {
document.querySelectorAll(".quant-btn").forEach(b => b.classList.remove("active"));
btn.classList.add("active");
send("/launch/quant", +btn.dataset.quant);
}));
}