atualizações em tempo real para as patterns na playlist
Deploy / Deploy (push) Successful in 2m22s Details

This commit is contained in:
JotaChina 2025-12-27 17:24:52 -03:00
parent 46105a8fb2
commit d003c2ccd6
1 changed files with 40 additions and 0 deletions

View File

@ -511,6 +511,39 @@ socket.on("action_broadcast", (payload) => {
const LMMS_BAR_TICKS = 192;
const STEPS_PER_BAR = 16;
// ticks por step (1/16) no LMMS: 192/16 = 12
const TICKS_PER_STEP = LMMS_BAR_TICKS / STEPS_PER_BAR;
function _syncNotesWithStepToggle(pattern, stepIndex, isActive) {
if (!pattern) return;
if (!Array.isArray(pattern.notes)) pattern.notes = [];
const pos = Math.round(stepIndex * TICKS_PER_STEP);
const samePos = (n) => Number(n?.pos) === pos;
if (isActive) {
// se já existe nota nesse step, não duplica
if (pattern.notes.some(samePos)) return;
// tenta reaproveitar "template" de nota pra manter key/vol/pan coerentes
const tpl = pattern.notes[0] || { vol: 100, len: TICKS_PER_STEP, pan: 0, key: 57 };
pattern.notes.push({
vol: tpl.vol ?? 100,
len: tpl.len ?? TICKS_PER_STEP,
pan: tpl.pan ?? 0,
key: tpl.key ?? 57,
pos,
});
pattern.notes.sort((a, b) => Number(a.pos) - Number(b.pos));
} else {
// remove todas as notas nesse step (útil inclusive pra "steps compostos")
pattern.notes = pattern.notes.filter((n) => !samePos(n));
}
}
function _makeEmptyPattern(idx) {
// tenta respeitar bars-input atual, mas nunca menos que 1 bar
const bars = parseInt(document.getElementById("bars-input")?.value, 10) || 1;
@ -1039,6 +1072,11 @@ async function handleActionBroadcast(action) {
t.patterns[pi].steps[si] = isActive;
_syncNotesWithStepToggle(t.patterns[pi], si, isActive);
// importante: se o Audio Editor estiver tocando, precisa re-schedulear
restartAudioEditorIfPlaying();
try { updateStepUI(ti, pi, si, isActive); } catch {}
if (!isFromSelf) schedulePatternRerender();
}
@ -1098,6 +1136,8 @@ async function handleActionBroadcast(action) {
// 5) Salva no sessionStorage
saveStateToSession();
restartAudioEditorIfPlaying();
break;
}
// Samples