feat(control): reglages group in morceau panel
Add the Reglages group to the morceau panel: two threshold sliders (open/close, the close one being the user-requested "sensibilite"), a transient-duration slider (1-8 bars), and a breakdown kept-voices checkbox grid covering all MATRIX_VOICES. Wired over /matrix/globalsettings with inbound sync and onOpen get-request. Imports consolidated into a single coherent block; no duplicate identifiers. DOM container added to index.html; styles appended to control.css.
This commit is contained in:
@@ -237,3 +237,11 @@ button.queued { animation: queued-blink 600ms ease-in-out infinite alternate; }
|
||||
gap: 6px; font-size: 13px; color: #ccc; }
|
||||
.morceau-slot select { flex: 0 0 auto; background: #222; color: #eee;
|
||||
border: 1px solid #444; border-radius: 4px; padding: 2px 4px; }
|
||||
|
||||
/* --- Réglages group --- */
|
||||
.morceau-settings { display: flex; flex-direction: column; gap: 4px; margin-top: 4px; }
|
||||
.morceau-set-row { display: grid; grid-template-columns: 1fr 2fr auto; align-items: center; gap: 6px; font-size: 12px; color: #ccc; }
|
||||
.morceau-set-row output { min-width: 2.5em; text-align: right; color: #8c8; }
|
||||
.morceau-keep { display: flex; flex-wrap: wrap; gap: 2px 8px; margin-top: 4px; font-size: 11px; color: #aaa; }
|
||||
.morceau-keep > span { flex-basis: 100%; color: #888; }
|
||||
.morceau-keep-box { display: inline-flex; align-items: center; gap: 2px; }
|
||||
|
||||
@@ -181,6 +181,8 @@
|
||||
<div id="morceau-panel" class="morceau-panel">
|
||||
<div class="morceau-title">Actions globales (morceau)</div>
|
||||
<div id="morceau-slots" class="morceau-slots"></div>
|
||||
<div class="morceau-title">Réglages</div>
|
||||
<div id="morceau-settings" class="morceau-settings"></div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
// matrix-state.js, transport over osc.js. Later phases add settings + global controls.
|
||||
import { send, on, onOpen } from "./osc.js";
|
||||
import {
|
||||
GLOBAL_ACTION_CHOICES, GLOBAL_SLOTS, matGlobalActions,
|
||||
setGlobalAction, saveMatState,
|
||||
GLOBAL_ACTION_CHOICES, GLOBAL_SLOTS, matGlobalActions, setGlobalAction, saveMatState,
|
||||
matGlobalSettings, setGlobalSetting, parseGlobalSettings,
|
||||
} from "./matrix-state.js";
|
||||
import { MATRIX_VOICES } from "./matrix-state.js";
|
||||
|
||||
export function init() {
|
||||
const host = document.getElementById("morceau-slots");
|
||||
@@ -31,6 +32,72 @@ export function init() {
|
||||
wrap.appendChild(sel);
|
||||
host.appendChild(wrap);
|
||||
});
|
||||
// --- Réglages: thresholds, transient duration, breakdown kept-voices ---
|
||||
const sHost = document.getElementById("morceau-settings");
|
||||
if (sHost) {
|
||||
const sendSettings = () => {
|
||||
const s = matGlobalSettings;
|
||||
send("/matrix/globalsettings", s.openThresh, s.closeThresh, s.transientBars,
|
||||
s.breakdownKeep.length, ...s.breakdownKeep);
|
||||
saveMatState();
|
||||
};
|
||||
const slider = (key, label, min, max, step) => {
|
||||
const row = document.createElement("label");
|
||||
row.className = "morceau-set-row";
|
||||
const span = document.createElement("span"); span.textContent = label;
|
||||
const inp = document.createElement("input");
|
||||
inp.type = "range"; inp.min = min; inp.max = max; inp.step = step;
|
||||
inp.value = matGlobalSettings[key];
|
||||
const out = document.createElement("output"); out.textContent = matGlobalSettings[key];
|
||||
inp.addEventListener("input", () => { out.textContent = inp.value; });
|
||||
inp.addEventListener("change", () => {
|
||||
setGlobalSetting(key, key === "transientBars" ? Math.round(+inp.value) : +inp.value);
|
||||
sendSettings();
|
||||
});
|
||||
row.append(span, inp, out);
|
||||
sHost.appendChild(row);
|
||||
return { inp, out };
|
||||
};
|
||||
const ctl = {
|
||||
openThresh: slider("openThresh", "Seuil ouvert", 0.5, 0.95, 0.01),
|
||||
closeThresh: slider("closeThresh", "Seuil fermé (sensibilité)", 0.05, 0.6, 0.01),
|
||||
transientBars: slider("transientBars", "Durée (mesures)", 1, 8, 1),
|
||||
};
|
||||
const keepWrap = document.createElement("div");
|
||||
keepWrap.className = "morceau-keep";
|
||||
const keepTitle = document.createElement("span");
|
||||
keepTitle.textContent = "Voix gardées (breakdown)";
|
||||
keepWrap.appendChild(keepTitle);
|
||||
const keepBoxes = {};
|
||||
MATRIX_VOICES.forEach((v) => {
|
||||
const lab = document.createElement("label"); lab.className = "morceau-keep-box";
|
||||
const cb = document.createElement("input"); cb.type = "checkbox"; cb.value = v;
|
||||
cb.checked = matGlobalSettings.breakdownKeep.includes(v);
|
||||
cb.addEventListener("change", () => {
|
||||
const keep = MATRIX_VOICES.filter((x) => keepBoxes[x].checked);
|
||||
setGlobalSetting("breakdownKeep", keep);
|
||||
sendSettings();
|
||||
});
|
||||
keepBoxes[v] = cb;
|
||||
lab.append(cb, document.createTextNode(v));
|
||||
keepWrap.appendChild(lab);
|
||||
});
|
||||
sHost.appendChild(keepWrap);
|
||||
on("/matrix/globalsettings", (args) => {
|
||||
const s = parseGlobalSettings(args);
|
||||
setGlobalSetting("openThresh", s.openThresh);
|
||||
setGlobalSetting("closeThresh", s.closeThresh);
|
||||
setGlobalSetting("transientBars", s.transientBars);
|
||||
setGlobalSetting("breakdownKeep", s.breakdownKeep);
|
||||
ctl.openThresh.inp.value = s.openThresh; ctl.openThresh.out.textContent = s.openThresh;
|
||||
ctl.closeThresh.inp.value = s.closeThresh; ctl.closeThresh.out.textContent = s.closeThresh;
|
||||
ctl.transientBars.inp.value = s.transientBars; ctl.transientBars.out.textContent = s.transientBars;
|
||||
MATRIX_VOICES.forEach((v) => { keepBoxes[v].checked = s.breakdownKeep.includes(v); });
|
||||
saveMatState();
|
||||
});
|
||||
onOpen(() => send("/matrix/globalsettings/get"));
|
||||
send("/matrix/globalsettings/get");
|
||||
}
|
||||
on("/matrix/globalaction", (args) => {
|
||||
const slot = Math.round(Number(args[0]));
|
||||
const id = String(args[1] || "none");
|
||||
|
||||
Reference in New Issue
Block a user