Padronização da interface e atualização do sync entre clientes
This commit is contained in:
1 parent
3f714c88de
commit
7d9d2b0f63
10 files changed
+796
-377
No files matched your search
+23
-31
@@ -1,4 +1,6 @@
|
||||
// js/file.js
|
||||
//--------------------------------------------------------------
|
||||
// IMPORTS NECESSÁRIOS
|
||||
//--------------------------------------------------------------
|
||||
import { appState, saveStateToSession, resetProjectState, loadStateFromSession } from "./state.js";
|
||||
import { loadAudioForTrack } from "./pattern/pattern_state.js";
|
||||
import { renderAll, getSamplePathMap } from "./ui.js";
|
||||
@@ -7,21 +9,13 @@ import {
|
||||
initializeAudioContext,
|
||||
getMainGainNode,
|
||||
} from "./audio.js";
|
||||
import { DEFAULT_PROJECT_XML } from "./utils.js"
|
||||
import * as Tone from "https://esm.sh/tone";
|
||||
|
||||
import { sendAction } from "./socket.js";
|
||||
|
||||
const BLANK_PROJECT_XML = `<?xml version="1.0"?>
|
||||
<!DOCTYPE lmms-project>
|
||||
<lmms-project type="song" version="1.0" creatorversion="1.2.2" creator="LMMS">
|
||||
<head bpm="140" mastervol="100" timesig_numerator="4" timesig_denominator="4" masterpitch="0"/>
|
||||
<song>
|
||||
<trackcontainer width="600" height="300" type="song" visible="1" maximized="0" x="5" y="5" minimized="0">
|
||||
</trackcontainer>
|
||||
<timeline lp0pos="0" lp1pos="192" lpstate="0"/>
|
||||
<controllers/>
|
||||
</song>
|
||||
</lmms-project>`;
|
||||
//--------------------------------------------------------------
|
||||
//
|
||||
//--------------------------------------------------------------
|
||||
|
||||
export function handleLocalProjectReset() {
|
||||
console.log("Recebido comando de reset. Limpando estado local...");
|
||||
@@ -89,7 +83,7 @@ export async function loadProjectFromServer(fileName) {
|
||||
export async function parseMmpContent(xmlString) {
|
||||
resetProjectState();
|
||||
initializeAudioContext();
|
||||
appState.global.justReset = xmlString === BLANK_PROJECT_XML;
|
||||
appState.global.justReset = xmlString === DEFAULT_PROJECT_XML;
|
||||
|
||||
const audioContainer = document.getElementById("audio-track-container");
|
||||
if (audioContainer) {
|
||||
@@ -305,10 +299,7 @@ export async function parseMmpContent(xmlString) {
|
||||
appState.pattern.activeTrackId = appState.pattern.tracks[0]?.id || null;
|
||||
appState.pattern.activePatternIndex = 0;
|
||||
|
||||
// --- SUBSTUIÇÃO DO BLOCO DE RESTAURAÇÃO ---
|
||||
// Em vez daquele bloco try/catch gigante, apenas chamamos a função:
|
||||
loadStateFromSession();
|
||||
// ------------------------------------------
|
||||
|
||||
await Promise.resolve();
|
||||
renderAll();
|
||||
@@ -324,17 +315,19 @@ export function generateMmpFile() {
|
||||
|
||||
function generateXmlFromState() {
|
||||
if (!appState.global.originalXmlDoc) {
|
||||
console.warn("Não há XML original. Retornando vazio.");
|
||||
return "";
|
||||
console.log("Gerando XML a partir do template em branco...");
|
||||
const parser = new DOMParser();
|
||||
appState.global.originalXmlDoc = parser.parseFromString(DEFAULT_PROJECT_XML, "application/xml");
|
||||
}
|
||||
|
||||
const xmlDoc = appState.global.originalXmlDoc.cloneNode(true);
|
||||
const head = xmlDoc.querySelector("head");
|
||||
|
||||
if (head) {
|
||||
head.setAttribute("bpm", document.getElementById("bpm-input").value);
|
||||
head.setAttribute("num_bars", document.getElementById("bars-input").value);
|
||||
head.setAttribute("timesig_numerator", document.getElementById("compasso-a-input").value);
|
||||
head.setAttribute("timesig_denominator", document.getElementById("compasso-b-input").value);
|
||||
head.setAttribute("bpm", document.getElementById("bpm-input").value || 140);
|
||||
head.setAttribute("num_bars", document.getElementById("bars-input").value || 1);
|
||||
head.setAttribute("timesig_numerator", document.getElementById("compasso-a-input").value || 4);
|
||||
head.setAttribute("timesig_denominator", document.getElementById("compasso-b-input").value || 4);
|
||||
}
|
||||
|
||||
const bbTrackContainer = xmlDoc.querySelector('track[type="1"] > bbtrack > trackcontainer');
|
||||
@@ -344,7 +337,6 @@ function generateXmlFromState() {
|
||||
.map((track) => createTrackXml(track))
|
||||
.join("");
|
||||
|
||||
// Gambiarra para inserir o XML gerado como nós DOM
|
||||
const tempDoc = new DOMParser().parseFromString(`<root>${tracksXml}</root>`, "application/xml");
|
||||
Array.from(tempDoc.documentElement.children).forEach((newTrackNode) => {
|
||||
bbTrackContainer.appendChild(newTrackNode);
|
||||
@@ -369,21 +361,22 @@ function createTrackXml(track) {
|
||||
const lmmsVolume = Math.round(track.volume * 100);
|
||||
const lmmsPan = Math.round(track.pan * 100);
|
||||
|
||||
// 🔥 PROTEÇÃO: Se não tiver instrumento definido, usa Kicker padrão
|
||||
const instrName = track.instrumentName || "kicker";
|
||||
const instrXml = track.instrumentXml || `<kicker><env amt="0" attack="0.01" hold="0.1" decay="0.1" release="0.1" sustain="0.5" sync_mode="0"/></kicker>`;
|
||||
|
||||
const patternsXml = track.patterns.map((pattern) => {
|
||||
let patternNotesXml = "";
|
||||
|
||||
// SE for plugin e tiver notas detalhadas, usa elas
|
||||
if (track.type === "plugin" && pattern.notes && pattern.notes.length > 0) {
|
||||
patternNotesXml = pattern.notes.map(note => {
|
||||
return `<note vol="${note.vol}" len="${note.len}" pos="${note.pos}" pan="${note.pan}" key="${note.key}"/>`;
|
||||
}).join("\n ");
|
||||
}
|
||||
// SE for sampler (ou plugin sem notas detalhadas), usa os steps convertidos em notas simples
|
||||
else {
|
||||
patternNotesXml = pattern.steps.map((isActive, index) => {
|
||||
if (isActive) {
|
||||
const notePos = Math.round(index * ticksPerStep);
|
||||
// Key 57 é o padrão do LMMS para samples (Lá)
|
||||
return `<note vol="100" len="${NOTE_LENGTH}" pos="${notePos}" pan="0" key="57"/>`;
|
||||
}
|
||||
return "";
|
||||
@@ -398,8 +391,8 @@ function createTrackXml(track) {
|
||||
return `
|
||||
<track type="0" solo="0" muted="0" name="${track.name}">
|
||||
<instrumenttrack vol="${lmmsVolume}" pitch="0" fxch="0" pitchrange="1" basenote="57" usemasterpitch="1" pan="${lmmsPan}">
|
||||
<instrument name="${track.instrumentName}">
|
||||
${track.instrumentXml}
|
||||
<instrument name="${instrName}">
|
||||
${instrXml}
|
||||
</instrument>
|
||||
<fxchain enabled="0" numofeffects="0"/>
|
||||
</instrumenttrack>
|
||||
@@ -461,5 +454,4 @@ function downloadFile(content, fileName) {
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
|
||||
export { generateXmlFromState as generateXmlFromStateExported };
|
||||
export { BLANK_PROJECT_XML }; // Mantenha o que já estava
|
||||
export { generateXmlFromState as generateXmlFromStateExported };
|
||||
Reference in new issue
Block a user