diff --git a/_config.yml b/_config.yml index 4a23d79..35eac18 100644 --- a/_config.yml +++ b/_config.yml @@ -4,8 +4,8 @@ description: >- # this means to ignore newlines until "baseurl:" Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description. -baseurl: "/mmpSearch/" # the subpath of your site, e.g. /blog -url: "https://alice.ufsj.edu.br" # the base hostname & protocol for your site, e.g. http://example.com +baseurl: "/~jotachina/mmpSearch/" # the subpath of your site, e.g. /blog +url: "https://alice.ufsj.edu.br/" # the base hostname & protocol for your site, e.g. http://example.com theme: alice diff --git a/_layouts/projetos.html b/_layouts/projetos.html index a40af5f..49731bd 100644 --- a/_layouts/projetos.html +++ b/_layouts/projetos.html @@ -8,10 +8,8 @@ title: "{{ page.file }}"
-

{{ page.file }}

- {% if page.file or page.bpm %}
@@ -29,114 +27,161 @@ title: "{{ page.file }}"
{% endif %} - - {% if page.tags %} - {% assign tags_vazias = true %} - {% for categoria in page.tags %} - {% if categoria[1].size > 0 %} - {% assign tags_vazias = false %} - {% endif %} - {% endfor %} - - {% unless tags_vazias %} -
- - {% assign audio_file = '/mmp/wav/' | append: page.file | append: '.wav' %} - - - {% if audio_file %} -
- -
- {% endif %} - -

🏷️ Tags

- {% for categoria in page.tags %} - {% if categoria[1].size > 0 %} -
- {{ categoria[0] }}: -
- {% for valor in categoria[1] %} - {% if valor != "" %} - {% assign tag_slug = valor | replace: ' ', '+' %} - - - {% if categoria[0] == 'bassline' %} - {{ valor }} - {% elsif categoria[0] == 'sample' %} - {{ valor }} - {% elsif categoria[0] == 'plugin' %} - {{ valor }} - {% elsif categoria[0] == 'automation' %} - {{ valor }} - {% else %} - {{ valor }} - {% endif %} - {% endif %} - {% endfor %} -
-
- {% endif %} - {% endfor %} -
- {% endunless %} - {% endif %} - - - {% if page.tracks and page.tracks.size > 0 %} -
-

🎚️ Instrumentos

-
-
    - {% for track in page.tracks %} - {% assign tem_instr = false %} - {% if track.instruments and track.instruments.size > 0 %} - {% assign tem_instr = true %} - {% endif %} - - {% if track.bassline_name or tem_instr %} -
  • - {% if track.bassline_name %} -

    🎼 {{ track.bassline_name }}

    - {% endif %} - - {% if tem_instr %} -
      - {% for instrument in track.instruments %} - {% if instrument.instrument_name %} -
    • - - {% assign instrument_slug = instrument.instrument_name | replace: ' ', '+' %} - - {{ instrument.instrument_name }} - - - {% if instrument.audiofileprocessor and instrument.audiofileprocessor.src %} - -
      - -
      - {% endif %} -
    • - {% endif %} - {% endfor %} -
    - {% endif %} -
  • +
    + +
    + + {% if page.tags %} + {% assign tags_vazias = true %} + {% for categoria in page.tags %} + {% if categoria[1].size > 0 %} + {% assign tags_vazias = false %} {% endif %} {% endfor %} -
-
-
- {% endif %} -
+ + {% unless tags_vazias %} +
+ {% assign audio_file = '/mmp/wav/' | append: page.file | append: '.wav' %} + + {% if audio_file %} +
+ +
+ {% endif %} + +

🏷️ Tags

+ {% for categoria in page.tags %} + {% if categoria[1].size > 0 %} +
+ {{ categoria[0] }}: +
+ {% for valor in categoria[1] %} + {% if valor != "" %} + {% assign tag_slug = valor | replace: ' ', '+' %} + + {% if categoria[0] == 'bassline' %} + {{ valor }} + {% elsif categoria[0] == 'sample' %} + {{ valor }} + {% elsif categoria[0] == 'plugin' %} + {{ valor }} + {% elsif categoria[0] == 'automation' %} + {{ valor }} + {% else %} + {{ valor }} + {% endif %} + {% endif %} + {% endfor %} +
+
+ {% endif %} + {% endfor %} +
+ {% endunless %} + {% endif %} + {% if page.tracks and page.tracks.size > 0 %} +
+

🎚️ Instrumentos

+
+
    + {% for track in page.tracks %} + {% assign tem_instr = false %} + {% if track.instruments and track.instruments.size > 0 %} + {% assign tem_instr = true %} + {% endif %} + + {% if track.bassline_name or tem_instr %} +
  • + {% if track.bassline_name %} +

    🎼 {{ track.bassline_name }}

    + {% endif %} + + {% if tem_instr %} +
      + {% for instrument in track.instruments %} + {% if instrument.instrument_name %} +
    • + {% assign instrument_slug = instrument.instrument_name | replace: ' ', '+' %} + + {{ instrument.instrument_name }} + + + {% if instrument.audiofileprocessor and instrument.audiofileprocessor.src %} + {% assign audio_filename_with_path = 'src/samples/' | append: instrument.audiofileprocessor.src %} +
      + +
      + {% endif %} +
    • + {% endif %} + {% endfor %} +
    + {% endif %} +
  • + {% endif %} + {% endfor %} +
+
+
+ {% endif %} +
+
+

🛠️ Abra na Criação Colaborativa

+ + {% comment %} + CONSTRUÇÃO DA URL: + 1. Usa o arquivo fonte (`page.file`) como parâmetro `project`. + 2. Assume que a plataforma de criação está em `/creations/`. + 3. Abre em uma nova aba (`target="_blank"`). + {% endcomment %} + {% assign creation_url = '/creations/?project=' | append: page.file | relative_url %} + + + + Abrir no MMPCreator + + +

+ O link abrirá o projeto em uma nova aba para edição. +
+ Arquivo: {{ page.file }} +

+ +
+

Prévia (Embed)

+ {% comment %} + A prévia embutida é opcional e pode ser um pouco pesada. + Ajuste o caminho da URL e o estilo (altura) conforme necessário. + {% endcomment %} + +
+
+
+
- + \ No newline at end of file diff --git a/assets/js/creations/main.js b/assets/js/creations/main.js index cc80184..5c9d572 100644 --- a/assets/js/creations/main.js +++ b/assets/js/creations/main.js @@ -25,6 +25,22 @@ import { sendAction, joinRoom, setUserName } from "./socket.js"; const ROOM_NAME = new URLSearchParams(window.location.search).get("room"); window.ROOM_NAME = ROOM_NAME; +const PROJECT_NAME = new URLSearchParams(window.location.search).get("project"); + +if (PROJECT_NAME) { + // O nome do projeto deve corresponder ao arquivo no servidor, por ex: "mmp/nome-do-seu-projeto-salvo.mmp" + // O arquivo 'file.js' já espera que loadProjectFromServer receba apenas o nome + // do arquivo dentro da pasta 'mmp/' (ex: 'nome-do-projeto.mmp'). + console.log(`[MAIN] Carregando projeto do servidor: ${PROJECT_NAME}`); + // Adicione a extensão se ela não estiver no link + const filename = PROJECT_NAME.endsWith('.mmp') || PROJECT_NAME.endsWith('.mmpz') + ? PROJECT_NAME + : `${PROJECT_NAME}.mmp`; + + // Chama a função de file.js para carregar (que já envia a ação 'LOAD_PROJECT') + loadProjectFromServer(filename); +} + // ✅ NOVO: se tem sala na URL, entra já na sala (independe do áudio) if (ROOM_NAME) { diff --git a/assets/js/creations/server/server.js b/assets/js/creations/server/server.js index e545654..05b64b5 100644 --- a/assets/js/creations/server/server.js +++ b/assets/js/creations/server/server.js @@ -518,6 +518,27 @@ io.on("connection", (socket) => { }); }); +// --- ENDPOINT DE NOTIFICAÇÃO EXTERNA --- +app.post("/notify-update", express.json(), (req, res) => { + const { updateType } = req.body; + + if (updateType === "samples") { + // 1. Emitir o evento para TODAS as salas/clientes. + // O evento deve ser algo que seu ui.js entenda. + io.emit("system_update", { + type: "RELOAD_SAMPLES", + message: "Novo Sample/Project adicionado. Recarregando o navegador de arquivos...", + }); + console.log( + "[Notificação] Evento 'RELOAD_SAMPLES' emitido para todos os clientes." + ); + + return res.status(200).send({ success: true, message: "Notificação de Samples/Projetos enviada." }); + } + + res.status(400).send({ success: false, message: "updateType inválido." }); +}); + app.get("/", (req, res) => { res.send( "Servidor Backend V6 (Logs Dinâmicos) da DAW colaborativa está no ar!" diff --git a/assets/js/creations/socket.js b/assets/js/creations/socket.js index 0456b1a..6db5f3c 100644 --- a/assets/js/creations/socket.js +++ b/assets/js/creations/socket.js @@ -165,6 +165,18 @@ socket.on("connect_error", (err) => { ); }); +socket.on("system_update", (data) => { + if (data.type === "RELOAD_SAMPLES") { + console.log(`[System Update] Recebida ordem para recarregar samples: ${data.message}`); + + // Certifique-se de que esta função existe e faz o que é esperado: + // 1. Fetch dos novos manifestos (metadata/samples-manifest.json etc.) + // 2. Renderiza a interface do navegador de samples + loadAndRenderSampleBrowser(); + } + // Se houver outras notificações, adicione-as aqui (ex: RELOAD_PROJECTS) +}); + // ----------------------------------------------------------------------------- // RECEBER ESTADO SALVO DA SALA // ----------------------------------------------------------------------------- @@ -803,4 +815,4 @@ async function handleActionBroadcast(action) { } // EXPORTS -export { socket }; +export { socket }; \ No newline at end of file diff --git a/mmpSearch/metadata/samples-manifest.json b/mmpSearch/metadata/samples-manifest.json new file mode 100644 index 0000000..f5f0903 --- /dev/null +++ b/mmpSearch/metadata/samples-manifest.json @@ -0,0 +1,773 @@ +{ + "basses": { + "bass01.ogg": { + "_isFile": true + }, + "bass_acid01.ogg": { + "_isFile": true + }, + "bass_acid02.ogg": { + "_isFile": true + }, + "bass_hard01.ogg": { + "_isFile": true + }, + "bass_hard02.ogg": { + "_isFile": true + }, + "bass_punch01.ogg": { + "_isFile": true + }, + "horror_bass01.ogg": { + "_isFile": true + }, + "matrix1000_pluck01.ogg": { + "_isFile": true + }, + "rave_bass01.ogg": { + "_isFile": true + }, + "rave_bass02.ogg": { + "_isFile": true + }, + "rave_bass04.ogg": { + "_isFile": true + }, + "synth_acid01.ogg": { + "_isFile": true + }, + "synth_acid02.ogg": { + "_isFile": true + }, + "techno_synth01.ogg": { + "_isFile": true + } + }, + "bassloops": { + "briff01.ogg": { + "_isFile": true + }, + "rave_bass01.ogg": { + "_isFile": true + }, + "rave_bass02.ogg": { + "_isFile": true + }, + "tb303_01.ogg": { + "_isFile": true + }, + "techno_bass01.ogg": { + "_isFile": true + }, + "techno_bass02.ogg": { + "_isFile": true + }, + "techno_synth01.ogg": { + "_isFile": true + }, + "techno_synth02.ogg": { + "_isFile": true + }, + "techno_synth03.ogg": { + "_isFile": true + }, + "techno_synth04.ogg": { + "_isFile": true + } + }, + "beats": { + "909beat01.ogg": { + "_isFile": true + }, + "break01.ogg": { + "_isFile": true + }, + "break02.ogg": { + "_isFile": true + }, + "break03.ogg": { + "_isFile": true + }, + "electro_beat01.ogg": { + "_isFile": true + }, + "electro_beat02.ogg": { + "_isFile": true + }, + "house_loop01.ogg": { + "_isFile": true + }, + "jungle01.ogg": { + "_isFile": true + }, + "rave_hihat01.ogg": { + "_isFile": true + }, + "rave_hihat02.ogg": { + "_isFile": true + }, + "rave_kick01.ogg": { + "_isFile": true + }, + "rave_kick02.ogg": { + "_isFile": true + }, + "rave_snare01.ogg": { + "_isFile": true + } + }, + "drums": { + "bassdrum01.ogg": { + "_isFile": true + }, + "bassdrum02.ogg": { + "_isFile": true + }, + "bassdrum03.ogg": { + "_isFile": true + }, + "bassdrum04.ogg": { + "_isFile": true + }, + "bassdrum_acoustic01.ogg": { + "_isFile": true + }, + "bassdrum_acoustic02.ogg": { + "_isFile": true + }, + "clap01.ogg": { + "_isFile": true + }, + "clap02.ogg": { + "_isFile": true + }, + "clap03.ogg": { + "_isFile": true + }, + "clap04.ogg": { + "_isFile": true + }, + "clav01.ogg": { + "_isFile": true + }, + "clav02.ogg": { + "_isFile": true + }, + "crash01.ogg": { + "_isFile": true + }, + "crash02.ogg": { + "_isFile": true + }, + "hihat_closed01.ogg": { + "_isFile": true + }, + "hihat_closed02.ogg": { + "_isFile": true + }, + "hihat_closed03.ogg": { + "_isFile": true + }, + "hihat_closed04.ogg": { + "_isFile": true + }, + "hihat_closed05.ogg": { + "_isFile": true + }, + "hihat_foot_pedal01.ogg": { + "_isFile": true + }, + "hihat_opened01.ogg": { + "_isFile": true + }, + "hihat_opened02.ogg": { + "_isFile": true + }, + "hihat_opened03.ogg": { + "_isFile": true + }, + "kick01.ogg": { + "_isFile": true + }, + "kick02.ogg": { + "_isFile": true + }, + "kick03.ogg": { + "_isFile": true + }, + "kick04.ogg": { + "_isFile": true + }, + "kick_distorted01.ogg": { + "_isFile": true + }, + "kick_hard01.ogg": { + "_isFile": true + }, + "kick_hardcore01.ogg": { + "_isFile": true + }, + "kick_hiphop01.ogg": { + "_isFile": true + }, + "kick_long01.ogg": { + "_isFile": true + }, + "kick_soft01.ogg": { + "_isFile": true + }, + "kick_soft02.ogg": { + "_isFile": true + }, + "nasty_bass01.ogg": { + "_isFile": true + }, + "nasty_rim01.ogg": { + "_isFile": true + }, + "nasty_snare01.ogg": { + "_isFile": true + }, + "ride01.ogg": { + "_isFile": true + }, + "ride02.ogg": { + "_isFile": true + }, + "rim01.ogg": { + "_isFile": true + }, + "shaker01.ogg": { + "_isFile": true + }, + "shaker02.ogg": { + "_isFile": true + }, + "shaker03.ogg": { + "_isFile": true + }, + "sidestick01.ogg": { + "_isFile": true + }, + "snare01.ogg": { + "_isFile": true + }, + "snare02.ogg": { + "_isFile": true + }, + "snare03.ogg": { + "_isFile": true + }, + "snare04.ogg": { + "_isFile": true + }, + "snare05.ogg": { + "_isFile": true + }, + "snare06.ogg": { + "_isFile": true + }, + "snare07.ogg": { + "_isFile": true + }, + "snare_acoustic01.ogg": { + "_isFile": true + }, + "snare_electro01.ogg": { + "_isFile": true + }, + "snare_harsh01.ogg": { + "_isFile": true + }, + "snare_hiphop01.ogg": { + "_isFile": true + }, + "snare_hiphop02.ogg": { + "_isFile": true + }, + "snare_muffled01.ogg": { + "_isFile": true + }, + "snare_muffled02.ogg": { + "_isFile": true + }, + "snare_rim01.ogg": { + "_isFile": true + }, + "snare_short01.ogg": { + "_isFile": true + }, + "tom01.ogg": { + "_isFile": true + }, + "tom02.ogg": { + "_isFile": true + }, + "tom03.ogg": { + "_isFile": true + }, + "tom04.ogg": { + "_isFile": true + }, + "tom05.ogg": { + "_isFile": true + }, + "tom_hi01.ogg": { + "_isFile": true + }, + "tom_low01.ogg": { + "_isFile": true + }, + "tom_mid01.ogg": { + "_isFile": true + }, + "wood01.ogg": { + "_isFile": true + }, + "zap01.ogg": { + "_isFile": true + }, + "zap02.ogg": { + "_isFile": true + }, + "zap03.ogg": { + "_isFile": true + } + }, + "drumsynth": { + "acoustic": {}, + "cr78": {}, + "cr8000": {}, + "effects": {}, + "electro": {}, + "farfisa": {}, + "ferraro": {}, + "instrument": {}, + "jorgensohn": {}, + "latin": {}, + "linn": {}, + "magnetboy": {}, + "misc": {}, + "misc_bass": {}, + "misc_claps": {}, + "misc_electro": {}, + "misc_fx": {}, + "misc_hats": {}, + "misc_perc": {}, + "misc_synth": {}, + "r_n_b": {}, + "tr606": {}, + "tr77": {}, + "tr808": {}, + "tr909": {} + }, + "effects": { + "chroma_sound_effect01.ogg": { + "_isFile": true + }, + "explode01.ogg": { + "_isFile": true + }, + "filter_sweep01.ogg": { + "_isFile": true + }, + "scratch01.ogg": { + "_isFile": true + }, + "start01.ogg": { + "_isFile": true + }, + "start02.ogg": { + "_isFile": true + }, + "stop01.ogg": { + "_isFile": true + }, + "warp01.ogg": { + "_isFile": true + }, + "warp02.ogg": { + "_isFile": true + }, + "wind_chimes01.ogg": { + "_isFile": true + } + }, + "instruments": { + "bassslap01.ogg": { + "_isFile": true + }, + "bassslap02.ogg": { + "_isFile": true + }, + "cello01.ogg": { + "_isFile": true + }, + "church_organ01.ogg": { + "_isFile": true + }, + "church_organ02.ogg": { + "_isFile": true + }, + "church_organ03.ogg": { + "_isFile": true + }, + "church_organ04.ogg": { + "_isFile": true + }, + "e_organ01.ogg": { + "_isFile": true + }, + "e_piano_accord01.ogg": { + "_isFile": true + }, + "e_piano_accord02.ogg": { + "_isFile": true + }, + "flute01.ogg": { + "_isFile": true + }, + "harpsichord01.ogg": { + "_isFile": true + }, + "piano01.ogg": { + "_isFile": true + }, + "piano02.ogg": { + "_isFile": true + }, + "steel_guitar01.ogg": { + "_isFile": true + }, + "steel_guitar_heavy_distorted01.ogg": { + "_isFile": true + }, + "steel_guitar_medium_distorted01.ogg": { + "_isFile": true + }, + "steel_guitar_slight_distorted01.ogg": { + "_isFile": true + }, + "trumpet01.ogg": { + "_isFile": true + }, + "violin_double_stop01.ogg": { + "_isFile": true + }, + "violin_fingered01.ogg": { + "_isFile": true + }, + "violin_pizzicato01.ogg": { + "_isFile": true + } + }, + "latin": { + "latin_brass01.ogg": { + "_isFile": true + }, + "latin_guitar01.ogg": { + "_isFile": true + }, + "latin_guitar02.ogg": { + "_isFile": true + }, + "latin_guitar03.ogg": { + "_isFile": true + } + }, + "misc": { + "applause01.ogg": { + "_isFile": true + }, + "bass!.ogg": { + "_isFile": true + }, + "breath01.ogg": { + "_isFile": true + }, + "buzz!.ogg": { + "_isFile": true + }, + "dong01.ogg": { + "_isFile": true + }, + "dong02.ogg": { + "_isFile": true + }, + "dong03.ogg": { + "_isFile": true + }, + "electric_ping01.ogg": { + "_isFile": true + }, + "hit01.ogg": { + "_isFile": true + }, + "hit02.ogg": { + "_isFile": true + }, + "metalish_dong01.ogg": { + "_isFile": true + }, + "metronome01.ogg": { + "_isFile": true + }, + "metronome02.ogg": { + "_isFile": true + }, + "raving_crowd01.ogg": { + "_isFile": true + }, + "snaph01.ogg": { + "_isFile": true + }, + "undefined01.ogg": { + "_isFile": true + } + }, + "samples": { + "reuniao_funkwhale.wav": { + "_isFile": true + } + }, + "shapes": { + "additive.wav": { + "_isFile": true + }, + "additive2.wav": { + "_isFile": true + }, + "bunglist.wav": { + "_isFile": true + }, + "bunglist2.wav": { + "_isFile": true + }, + "bunglist3.wav": { + "_isFile": true + }, + "bunglist4.wav": { + "_isFile": true + }, + "bunglist5.wav": { + "_isFile": true + }, + "bunglist6.wav": { + "_isFile": true + }, + "bunglist7.wav": { + "_isFile": true + }, + "bunglist8.wav": { + "_isFile": true + }, + "bunglist9.wav": { + "_isFile": true + }, + "harmonics.wav": { + "_isFile": true + }, + "low_sine.wav": { + "_isFile": true + }, + "micro.wav": { + "_isFile": true + }, + "moog.wav": { + "_isFile": true + }, + "roundbass.wav": { + "_isFile": true + }, + "roundsaw.ogg": { + "_isFile": true + }, + "saw+sine.wav": { + "_isFile": true + }, + "sine_dist.ogg": { + "_isFile": true + }, + "smooth_inv_saw.ogg": { + "_isFile": true + }, + "smooth_inv_saw2.ogg": { + "_isFile": true + }, + "smooth_inv_saw_dist.ogg": { + "_isFile": true + }, + "technobass.wav": { + "_isFile": true + }, + "technosynth1.wav": { + "_isFile": true + }, + "technosynth2.wav": { + "_isFile": true + }, + "technosynth3.wav": { + "_isFile": true + }, + "technosynth4.wav": { + "_isFile": true + }, + "technosynth5.wav": { + "_isFile": true + }, + "technosynth6.wav": { + "_isFile": true + }, + "vowel_a.wav": { + "_isFile": true + }, + "vowel_u.wav": { + "_isFile": true + } + }, + "stringsnpads": { + "bell_choir01.ogg": { + "_isFile": true + }, + "bell_choir02.ogg": { + "_isFile": true + }, + "chorus01.ogg": { + "_isFile": true + }, + "chorus02.ogg": { + "_isFile": true + }, + "heaven_strings01.ogg": { + "_isFile": true + }, + "juno_pad01.ogg": { + "_isFile": true + }, + "korg_poly6_drone01.ogg": { + "_isFile": true + }, + "nord_ambient01.ogg": { + "_isFile": true + }, + "orion_string01.ogg": { + "_isFile": true + }, + "rave_choir01.ogg": { + "_isFile": true + }, + "space_strings01.ogg": { + "_isFile": true + }, + "space_strings02.ogg": { + "_isFile": true + }, + "space_strings03.ogg": { + "_isFile": true + }, + "strings01.ogg": { + "_isFile": true + } + }, + "waveforms": { + "10saw.flac": { + "_isFile": true + }, + "10sine.flac": { + "_isFile": true + }, + "10sqr.flac": { + "_isFile": true + }, + "10tri.flac": { + "_isFile": true + }, + "analogsqr.flac": { + "_isFile": true + }, + "fmsaw1.flac": { + "_isFile": true + }, + "fmsine.flac": { + "_isFile": true + }, + "fmsine2.flac": { + "_isFile": true + }, + "halfsine.flac": { + "_isFile": true + }, + "impulse.flac": { + "_isFile": true + }, + "lfo_trancegate_quarter.flac": { + "_isFile": true + }, + "lfo_trancegate_sawdecay_quarter.flac": { + "_isFile": true + }, + "lfo_trancegate_sinedecay_quarter.flac": { + "_isFile": true + }, + "lfo_trancegate_triplet_half.flac": { + "_isFile": true + }, + "lfo_trancegate_triplet_half_2.flac": { + "_isFile": true + }, + "lfo_trancegate_triplet_quarter.flac": { + "_isFile": true + }, + "lfo_trancegate_whole.flac": { + "_isFile": true + }, + "lfo_trancegate_whole_2.flac": { + "_isFile": true + }, + "modsqr.flac": { + "_isFile": true + }, + "saw1.flac": { + "_isFile": true + }, + "saw2.flac": { + "_isFile": true + }, + "sinesaw.flac": { + "_isFile": true + }, + "w2_addsyn.flac": { + "_isFile": true + }, + "w2_angrysaw.flac": { + "_isFile": true + }, + "w2_hexagon.flac": { + "_isFile": true + }, + "w2_invsine.flac": { + "_isFile": true + }, + "w2_invsineabs.flac": { + "_isFile": true + }, + "w2_invsinehalf.flac": { + "_isFile": true + }, + "w2_noisy.flac": { + "_isFile": true + }, + "w2_rad.flac": { + "_isFile": true + }, + "w2_sawsine.flac": { + "_isFile": true + }, + "w2_sharp.flac": { + "_isFile": true + }, + "w2_w-wave.flac": { + "_isFile": true + } + } +} \ No newline at end of file diff --git a/upload_server.py b/upload_server.py index 8965372..84bffe8 100644 --- a/upload_server.py +++ b/upload_server.py @@ -8,6 +8,9 @@ from werkzeug.utils import secure_filename from flask_cors import CORS from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler +import requests + +NODE_SERVER_URL = "https://127.0.0.1:33001" # --- Configurações (sem alterações) --- PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) @@ -27,13 +30,16 @@ CONFIGS = [ } ] -UPLOAD_FOLDER = os.path.join(PROJECT_ROOT, "src", "samples", "samples") -WATCH_FOLDER = os.path.join(PROJECT_ROOT, "src", "samples") # Pasta a ser vigiada +UPLOAD_FOLDER_SAMPLE = os.path.join(PROJECT_ROOT, "src", "samples", "samples") +WATCH_FOLDER_SAMPLE = UPLOAD_FOLDER_SAMPLE # Pasta a ser vigiada +UPLOAD_FOLDER_PROJECT = os.path.join(PROJECT_ROOT, "src", "samples", "projects") +WATCH_FOLDER_PROJECT = os.path.join(PROJECT_ROOT, "src", "upload_projects") # Pasta a ser vigiada + ALLOWED_EXTENSIONS = {'wav', 'ogg', 'flac', 'mp3'} app = Flask(__name__) -CORS(app, origins=["https://alice.ufsj.edu.br", "http://localhost:8000", "http://127.0.0.1:5500"]) -app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER +CORS(app, origins=["https://alice.ufsj.edu.br", "https://alice.ufsj.edu.br:33002"]) +app.config['UPLOAD_FOLDER_SAMPLE'] = UPLOAD_FOLDER_SAMPLE # --- Funções do Gerador de Manifesto (sem alterações) --- def scan_directory_tree(path): @@ -75,9 +81,27 @@ def run_jekyll_build(): except Exception as e: print(f"ERRO inesperado durante o Jekyll build: {e}") +def notify_node_server(update_type): + """Envia uma notificação HTTP para o servidor Node.js.""" + try: + url = f"{NODE_SERVER_URL}/notify-update" + headers = {'Content-Type': 'application/json'} + payload = {"updateType": update_type} + + # O argumento 'verify=False' é geralmente necessário ao usar 127.0.0.1 + # com certificados Let's Encrypt (ou autoassinados) para evitar erros de SSL. + response = requests.post(url, json=payload, headers=headers, verify=False) + + if response.status_code == 200: + print(f"[Notificação] Sucesso ao notificar Node.js: {update_type}") + else: + print(f"[Notificação] ERRO ao notificar Node.js ({response.status_code}): {response.text}") + + except Exception as e: + print(f"[Notificação] ERRO de conexão com o Node.js em {NODE_SERVER_URL}: {e}") + def generate_manifests(): print("\nIniciando geração de arquivos de manifesto...") - # ... (lógica interna sem alterações) ... for config in CONFIGS: source_dir_abs = os.path.join(PROJECT_ROOT, config["source_dir"]) output_file_abs = os.path.join(PROJECT_ROOT, config["output_file"]) @@ -93,8 +117,10 @@ def generate_manifests(): print(f"SUCESSO: Arquivo '{output_file_abs}' gerado!") print("\nGeração de manifestos concluída.") run_jekyll_build() + # 2. NOTIFICA O SERVIDOR NODE.JS (NOVO PASSO) + notify_node_server("samples") -# --- Lógica do Servidor Flask (sem alterações) --- +# --- Servidor Flask --- def allowed_file(filename): return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS @@ -105,41 +131,58 @@ def upload_file(): if file.filename == '': return jsonify({"error": "Nenhum arquivo selecionado"}), 400 if file and allowed_file(file.filename): filename = secure_filename(file.filename) - os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) - save_path = os.path.join(app.config['UPLOAD_FOLDER'], filename) + os.makedirs(app.config['UPLOAD_FOLDER_SAMPLE'], exist_ok=True) + save_path = os.path.join(app.config['UPLOAD_FOLDER_SAMPLE'], filename) try: - file.save(save_path) - generate_manifests() - return jsonify({"success": True, "message": f"Arquivo '{filename}' salvo e site atualizado!"}), 200 + file.save(save_path) + return jsonify({"success": True, "message": f"Arquivo '{filename}' salvo!"}), 200 except Exception as e: return jsonify({"error": str(e)}), 500 return jsonify({"error": "Tipo de arquivo não permitido"}), 400 -# --- NOVO: LÓGICA DO "VIGIA" DE ARQUIVOS (WATCHDOG) --- +# --- LÓGICA DO "VIGIA" DE ARQUIVOS (WATCHDOG) --- class ManifestEventHandler(FileSystemEventHandler): """Um manipulador de eventos que gera os manifestos quando um arquivo muda.""" def __init__(self): + # Inicializa o timestamp da última execução self.last_triggered = 0 + # Define o intervalo mínimo entre execuções (5 segundos) + self.debounce_interval = 5 def on_any_event(self, event): - # Desconsidera eventos em diretórios - if event.is_directory: + # Ignora eventos em diretórios ou no arquivo de manifesto de saída (evita loop) + if event.is_directory or "manifest" in event.src_path: return - # Mecanismo simples para evitar múltiplas execuções seguidas (debounce) current_time = time.time() - if current_time - self.last_triggered > 5: # Espera 5 segundos entre as atualizações + + # Verifica se passou tempo suficiente desde o último acionamento + if current_time - self.last_triggered > self.debounce_interval: print(f"\n[VIGIA] Mudança detectada: {event.src_path}") - generate_manifests() + + # Executa a geração de manifestos (e o Jekyll build, se descomentado) + # É crucial que generate_manifests() seja rápido ou executado em outra thread separada + # para não bloquear o Watchdog por muito tempo. + Thread(target=generate_manifests).start() + self.last_triggered = current_time + else: + print(f"[VIGIA] Mudança ignorada devido ao debounce (Intervalo de {self.debounce_interval}s).") def start_file_watcher(): - """Inicia o observador de arquivos em uma thread separada.""" - print(f"\n[VIGIA] Iniciando monitoramento da pasta: {WATCH_FOLDER}") + """Inicia o observador de arquivos para ambas as pastas em uma thread separada.""" event_handler = ManifestEventHandler() observer = Observer() - observer.schedule(event_handler, WATCH_FOLDER, recursive=True) + + # 1. Monitorar a pasta de Samples + print(f"\n[VIGIA] Monitorando Samples: {WATCH_FOLDER_SAMPLE}") + observer.schedule(event_handler, WATCH_FOLDER_SAMPLE, recursive=True) + + # 2. Monitorar a pasta de Projetos + print(f"[VIGIA] Monitorando Projetos: {WATCH_FOLDER_PROJECT}") + observer.schedule(event_handler, WATCH_FOLDER_PROJECT, recursive=True) + observer.start() try: while True: @@ -160,4 +203,4 @@ if __name__ == '__main__': # Inicia o servidor Flask (thread principal) print("\n[FLASK] Iniciando servidor de upload...") - app.run(host='0.0.0.0', port=5000, debug=False) # Debug mode deve ser False para evitar que rode duas vezes \ No newline at end of file + app.run(host='0.0.0.0', port=33002, debug=True) # Debug mode deve ser False para evitar que rode duas vezes