diff --git a/assets/js/creations/file.js b/assets/js/creations/file.js index 6282b8c4..5161d3e4 100644 --- a/assets/js/creations/file.js +++ b/assets/js/creations/file.js @@ -1,5 +1,5 @@ // js/file.js -import { appState, saveStateToSession, resetProjectState } from "./state.js"; +import { appState, saveStateToSession, resetProjectState, loadStateFromSession } from "./state.js"; import { loadAudioForTrack } from "./pattern/pattern_state.js"; import { renderAll, getSamplePathMap } from "./ui.js"; import { DEFAULT_PAN, DEFAULT_VOLUME, NOTE_LENGTH } from "./config.js"; diff --git a/assets/js/creations/server/data/2025-11-24_16-03-07_sessao-uq5ef.log b/assets/js/creations/server/data/2025-11-24_16-03-07_sessao-uq5ef.log new file mode 100644 index 00000000..f8ee295e --- /dev/null +++ b/assets/js/creations/server/data/2025-11-24_16-03-07_sessao-uq5ef.log @@ -0,0 +1,10 @@ +{"level":30,"time":1764010987925,"pid":1793,"hostname":"ubuntu","timestamp":1764010987925,"socketId":"0-VWQV4Ty3AEFZS8AALy","action":{"type":"LOAD_PROJECT","xml":"\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n

Música para o primeiro projeto de Computação Musical:
Essa música foi feita por mim com base na última aula de rap que tivemos (afinal eu sou muito rapper) e com base no meu amor pelos pets, tendo miados de gato (pegados no freesound) e latidos da minha gatinha Emy.

]]>
\n \n \n
\n
\n\n","__token":"1","__senderId":"0-VWQV4Ty3AEFZS8AALy","__senderName":"Alicer-0-VW"},"msg":"action_received"} +{"level":30,"time":1764011196043,"pid":1793,"hostname":"ubuntu","timestamp":1764011196043,"socketId":"RmmiTfGQS9U5IIQLAAL4","action":{"type":"LOAD_PROJECT","xml":"\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n

Universidade Federal de São João del-Rei

\n

Departamento de Ciência da Computação

\n

Introdução a Computação Musical

\n

1º Semestre de 2024

\n

Prof. Flávio Schiavoni

\n

Trabalho Prático 1

\n

Samanta Ribeiro Freire

\n

192050022

]]>
\n \n \n
\n
\n\n","__token":"1","__senderId":"RmmiTfGQS9U5IIQLAAL4","__senderName":"Alicer-Rmmi"},"msg":"action_received"} +{"level":30,"time":1764011341399,"pid":1793,"hostname":"ubuntu","timestamp":1764011341399,"socketId":"zIHbT0kdb2NadRJXAAL6","action":{"type":"AUDIO_SNAPSHOT_REQUEST","__token":"1","__senderId":"zIHbT0kdb2NadRJXAAL6","__senderName":"Alicer-zIHb"},"msg":"action_received"} +{"level":30,"time":1764011352194,"pid":1793,"hostname":"ubuntu","timestamp":1764011352194,"socketId":"2gcwQT0EQ9fEEsP5AAL8","action":{"type":"AUDIO_SNAPSHOT_REQUEST","__token":"1","__senderId":"2gcwQT0EQ9fEEsP5AAL8","__senderName":"Alicer-2gcw"},"msg":"action_received"} +{"level":30,"time":1764011360946,"pid":1793,"hostname":"ubuntu","timestamp":1764011360946,"socketId":"2gcwQT0EQ9fEEsP5AAL8","action":{"type":"LOAD_PROJECT","xml":"\n\n\n \n \n \n \n \n \n \n","__token":"2","__senderId":"2gcwQT0EQ9fEEsP5AAL8","__senderName":"Alicer-2gcw"},"msg":"action_received"} +{"level":30,"time":1764011363860,"pid":1793,"hostname":"ubuntu","timestamp":1764011363860,"socketId":"cMOxnhsbtMWY0l7vAAL-","action":{"type":"AUDIO_SNAPSHOT_REQUEST","__token":"1","__senderId":"cMOxnhsbtMWY0l7vAAL-","__senderName":"Alicer-cMOx"},"msg":"action_received"} +{"level":30,"time":1764011368647,"pid":1793,"hostname":"ubuntu","timestamp":1764011368647,"socketId":"JW_-sEko8rqJ3JpNAAMA","action":{"type":"AUDIO_SNAPSHOT_REQUEST","__token":"1","__senderId":"JW_-sEko8rqJ3JpNAAMA","__senderName":"Alicer-JW_-"},"msg":"action_received"} +{"level":30,"time":1764011372581,"pid":1793,"hostname":"ubuntu","timestamp":1764011372581,"socketId":"PHsgLGs_6ldNLuODAAMC","action":{"type":"AUDIO_SNAPSHOT_REQUEST","__token":"1","__senderId":"PHsgLGs_6ldNLuODAAMC","__senderName":"Alicer-PHsg"},"msg":"action_received"} +{"level":30,"time":1764011377940,"pid":1793,"hostname":"ubuntu","timestamp":1764011377940,"socketId":"8I1DK7i86zWN7d2pAAME","action":{"type":"AUDIO_SNAPSHOT_REQUEST","__token":"1","__senderId":"8I1DK7i86zWN7d2pAAME","__senderName":"Alicer-8I1D"},"msg":"action_received"} +{"level":30,"time":1764011386916,"pid":1793,"hostname":"ubuntu","timestamp":1764011386916,"socketId":"8I1DK7i86zWN7d2pAAME","action":{"type":"LOAD_PROJECT","xml":"\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n

Música para o primeiro projeto de Computação Musical:
Essa música foi feita por mim com base na última aula de rap que tivemos (afinal eu sou muito rapper) e com base no meu amor pelos pets, tendo miados de gato (pegados no freesound) e latidos da minha gatinha Emy.

]]>
\n \n \n
\n
\n\n","__token":"2","__senderId":"8I1DK7i86zWN7d2pAAME","__senderName":"Alicer-8I1D"},"msg":"action_received"} diff --git a/assets/js/creations/server/data/sessao-uq5ef.json b/assets/js/creations/server/data/sessao-uq5ef.json new file mode 100644 index 00000000..7185e842 --- /dev/null +++ b/assets/js/creations/server/data/sessao-uq5ef.json @@ -0,0 +1 @@ +{"projectXml":"\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n

Música para o primeiro projeto de Computação Musical:
Essa música foi feita por mim com base na última aula de rap que tivemos (afinal eu sou muito rapper) e com base no meu amor pelos pets, tendo miados de gato (pegados no freesound) e latidos da minha gatinha Emy.

]]>
\n \n \n
\n
\n\n","audio":{"tracks":[],"clips":[]},"seq":0} \ No newline at end of file diff --git a/assets/js/creations/socket.js b/assets/js/creations/socket.js index 2a798026..bb8d4ead 100644 --- a/assets/js/creations/socket.js +++ b/assets/js/creations/socket.js @@ -3,7 +3,7 @@ // -------------------relómm------------------------------------------------------ // IMPORTS & STATE // ----------------------------------------------------------------------------- -import { appState, saveStateToSession } from "./state.js"; +import { appState, saveStateToSession, loadStateFromSession } from "./state.js"; import { addTrackToState, removeLastTrackFromState, diff --git a/assets/js/creations/state.js b/assets/js/creations/state.js index 827f7ba8..17b7e3a2 100644 --- a/assets/js/creations/state.js +++ b/assets/js/creations/state.js @@ -1,10 +1,16 @@ // js/state.js -import { initializePatternState } from "./pattern/pattern_state.js"; import { audioState, initializeAudioState } from "./audio/audio_state.js"; import { DEFAULT_VOLUME, DEFAULT_PAN } from "./config.js"; -import * as Tone from "https://esm.sh/tone"; // Adicione esta importação +import * as Tone from "https://esm.sh/tone"; + +// --- DEFINIÇÃO DOS ESTADOS INICIAIS --- + +const patternState = { + tracks: [], + activeTrackId: null, + activePatternIndex: 0, +}; -// Estado global da aplicação const globalState = { sliceToolActive: false, isPlaying: false, @@ -26,16 +32,9 @@ const globalState = { clipboard: null, lastRulerClickTime: 0, justReset: false, + syncMode: "global", }; -// Define o ESTADO INICIAL para o pattern module -const patternState = { - tracks: [], - activeTrackId: null, - activePatternIndex: 0, -}; - -// Combina todos os estados em um único objeto namespaced export let appState = { global: globalState, pattern: patternState, @@ -44,9 +43,9 @@ export let appState = { window.appState = appState; export function resetProjectState() { - console.log("Executando resetProjectState completo..."); + console.log("Executando resetProjectState (Limpeza Profunda)..."); - // 1. Reseta o estado global + // 1. Reseta Global Object.assign(appState.global, { sliceToolActive: false, isPlaying: false, @@ -68,52 +67,68 @@ export function resetProjectState() { clipboard: null, lastRulerClickTime: 0, justReset: false, + // syncMode mantemos o que estava }); - // 2. Reseta o estado do pattern + // 2. Reseta Pattern Object.assign(appState.pattern, { tracks: [], activeTrackId: null, activePatternIndex: 0, }); - // 3. Reseta o estado de áudio (Força bruta para garantir limpeza na memória) + // 3. Reseta Áudio (Remove tudo da memória) if (appState.audio) { appState.audio.tracks = []; appState.audio.clips = []; appState.audio.audioEditorSeekTime = 0; } - initializeAudioState(); } +/** + * SALVAR (Serialization): + * Transforma o estado complexo em um JSON leve (apenas strings e números). + * Remove objetos cíclicos como AudioBuffers e Nodes do Tone.js. + */ export function saveStateToSession() { if (!window.ROOM_NAME) return; - // 1. Crie uma versão "limpa" dos tracks - const cleanTracks = appState.pattern.tracks.map((track) => { - return { - id: track.id, - name: track.name, - samplePath: track.samplePath, - patterns: track.patterns, - activePatternIndex: track.activePatternIndex, - volume: track.volume, - pan: track.pan, - instrumentName: track.instrumentName, - instrumentXml: track.instrumentXml, - }; - }); + // 1. Sanitiza Tracks do Pattern (Instrumentos) + const cleanPatternTracks = appState.pattern.tracks.map((track) => ({ + id: track.id, + name: track.name, + samplePath: track.samplePath, // Caminho do arquivo (String) + patterns: track.patterns, + activePatternIndex: track.activePatternIndex, + volume: track.volume, + pan: track.pan, + instrumentName: track.instrumentName, + instrumentXml: track.instrumentXml, + // Note: NÃO salvamos volumeNode, pannerNode, etc. + })); + + // 2. Sanitiza Clipes de Áudio (Timeline) + // AQUI ESTÁ O SEGREDO: Salvamos apenas o 'filePath', não o buffer de áudio. + const cleanAudioClips = (appState.audio.clips || []).map((clip) => ({ + id: clip.id, + trackId: clip.trackId, + name: clip.name, + filePath: clip.filePath, // O endereço do áudio + startTimeInSeconds: clip.startTimeInSeconds, + durationInSeconds: clip.durationInSeconds, + offset: clip.offset, + pitch: clip.pitch, + originalDuration: clip.originalDuration, + patternData: clip.patternData, // Visualização dos steps (leve) + // Note: NÃO salvamos clip.buffer (que é o áudio pesado) + })); - // 2. Construa o objeto de estado final para salvar const stateToSave = { - pattern: { - ...appState.pattern, - tracks: cleanTracks, - }, - audio: { - tracks: appState.audio.tracks || [], - clips: appState.audio.clips || [], + pattern: { ...appState.pattern, tracks: cleanPatternTracks }, + audio: { + tracks: appState.audio.tracks || [], // Tracks são apenas containers leves + clips: cleanAudioClips }, global: { bpm: document.getElementById("bpm-input")?.value || 140, @@ -126,78 +141,98 @@ export function saveStateToSession() { try { const roomName = window.ROOM_NAME || "default_room"; - sessionStorage.setItem( - `temp_state_${roomName}`, - JSON.stringify(stateToSave) - ); + // Agora o JSON.stringify funciona porque só tem dados simples + sessionStorage.setItem(`temp_state_${roomName}`, JSON.stringify(stateToSave)); } catch (e) { - console.error("Falha ao salvar estado na sessão:", e); + console.error("Erro ao salvar sessão:", e); } } -// --- NOVA FUNÇÃO PARA CORRIGIR O ERRO --- -export function loadStateFromSession() { +/** + * CARREGAR (Hydration): + * Lê o JSON leve e RECONSTRÓI os objetos pesados (carrega os arquivos via HTTP). + */ +export async function loadStateFromSession() { const roomName = window.ROOM_NAME || "default_room"; const tempStateJSON = sessionStorage.getItem(`temp_state_${roomName}`); if (!tempStateJSON) return false; - console.log("Restaurando estado da sessão..."); + console.log("Hidratando estado da sessão..."); try { const tempState = JSON.parse(tempStateJSON); // 1. Restaura Pattern Tracks + // Precisamos recriar os Nodes do Tone.js que não foram salvos appState.pattern.tracks.forEach((liveTrack) => { - const savedTrack = tempState.pattern.tracks.find( - (t) => t.id === liveTrack.id - ); + const savedTrack = tempState.pattern.tracks.find(t => t.id === liveTrack.id); if (savedTrack) { - liveTrack.name = savedTrack.name; - liveTrack.patterns = savedTrack.patterns; - liveTrack.activePatternIndex = savedTrack.activePatternIndex; - liveTrack.volume = savedTrack.volume; - liveTrack.pan = savedTrack.pan; - - if (liveTrack.volumeNode) { - liveTrack.volumeNode.volume.value = Tone.gainToDb(savedTrack.volume); - } - if (liveTrack.pannerNode) { - liveTrack.pannerNode.pan.value = savedTrack.pan; - } + // Copia dados simples + Object.assign(liveTrack, { + name: savedTrack.name, + patterns: savedTrack.patterns, + activePatternIndex: savedTrack.activePatternIndex, + volume: savedTrack.volume, + pan: savedTrack.pan + }); + + // Reconecta Nodes de Áudio (Hidratação) + if (liveTrack.volumeNode) liveTrack.volumeNode.volume.value = Tone.gainToDb(savedTrack.volume); + if (liveTrack.pannerNode) liveTrack.pannerNode.pan.value = savedTrack.pan; } }); - - // Filtra tracks que não existem mais no salvo - appState.pattern.tracks = appState.pattern.tracks.filter((liveTrack) => - tempState.pattern.tracks.some((t) => t.id === liveTrack.id) + + // Sincroniza lista de tracks (remove deletadas) + appState.pattern.tracks = appState.pattern.tracks.filter(liveTrack => + tempState.pattern.tracks.some(t => t.id === liveTrack.id) ); - // 2. Restaura Áudio + // 2. Restaura Áudio Timeline (A parte mais importante) if (tempState.audio) { appState.audio.tracks = tempState.audio.tracks || []; - appState.audio.clips = tempState.audio.clips || []; + + const clipsMetadata = tempState.audio.clips || []; + const loadedClips = []; + + console.log(`Recarregando ${clipsMetadata.length} clips de áudio...`); + + // Para cada clipe salvo, baixamos o áudio novamente usando o filePath + for (const metaClip of clipsMetadata) { + let buffer = null; + if (metaClip.filePath) { + try { + // Tone.Buffer carrega o arquivo .wav/.mp3 da URL + buffer = await new Tone.Buffer(metaClip.filePath).loaded; + } catch (err) { + console.warn(`Arquivo não encontrado: ${metaClip.filePath}`, err); + } + } + + // Recria o objeto completo na memória + loadedClips.push({ + ...metaClip, // Pega id, start, duration, pitch... + buffer: buffer // Anexa o áudio pesado recém-carregado + }); + } + appState.audio.clips = loadedClips; } - // 3. Restaura Global + // 3. Restaura Global UI if (tempState.global) { - const bpmInput = document.getElementById("bpm-input"); - if (bpmInput) bpmInput.value = tempState.global.bpm; + const g = tempState.global; + const setVal = (id, val) => { const el = document.getElementById(id); if(el) el.value = val; }; - const compassoA = document.getElementById("compasso-a-input"); - if (compassoA) compassoA.value = tempState.global.compassoA; + setVal("bpm-input", g.bpm); + setVal("compasso-a-input", g.compassoA); + setVal("compasso-b-input", g.compassoB); + setVal("bars-input", g.bars); - const compassoB = document.getElementById("compasso-b-input"); - if (compassoB) compassoB.value = tempState.global.compassoB; - - const barsInput = document.getElementById("bars-input"); - if (barsInput) barsInput.value = tempState.global.bars; - - if (tempState.global.syncMode) { - appState.global.syncMode = tempState.global.syncMode; - const syncBtn = document.getElementById("sync-mode-btn"); - if (syncBtn) { - syncBtn.classList.toggle("active", tempState.global.syncMode === "global"); - syncBtn.textContent = tempState.global.syncMode === "global" ? "Global" : "Local"; + if (g.syncMode) { + appState.global.syncMode = g.syncMode; + const btn = document.getElementById("sync-mode-btn"); + if (btn) { + btn.classList.toggle("active", g.syncMode === "global"); + btn.textContent = g.syncMode === "global" ? "Global" : "Local"; } } } @@ -205,7 +240,7 @@ export function loadStateFromSession() { appState.pattern.activeTrackId = tempState.pattern.activeTrackId; return true; } catch (e) { - console.error("Erro ao carregar estado da sessão:", e); + console.error("Erro crítico ao carregar sessão:", e); return false; } } \ No newline at end of file