diff --git a/_data/all.yml b/_data/all.yml index b7af7800..82fe3b0c 100644 --- a/_data/all.yml +++ b/_data/all.yml @@ -260447,8 +260447,7 @@ looped: '0' reversed: '0' sframe: '0' - src: Young Kico - Chronicles Of The Atlantic Trap (Sound Kit) @YoungKico/01 - Kicks/Kick 1 (Layer With Any 808 For Authentic Zaytoven Delayed Kick).wav + src: /var/www/html/trens/src_mmpSearch/samples/imported/bassdrum_acoustic01_-_Copia.ogg stutter: '0' basenote: '57' fxch: '0' @@ -260615,7 +260614,7 @@ looped: '0' reversed: '0' sframe: '0' - src: lex_luger_drum_kit/lex_luger_drum_kit/LEX Rim(2).wav + src: /var/www/html/trens/src_mmpSearch/samples/imported/bassdrum_acoustic02_-_Copia.ogg stutter: '0' basenote: '57' fxch: '0' @@ -260939,7 +260938,7 @@ looped: '0' reversed: '0' sframe: '0' - src: Kid Urban Christmas BeatKit/Urban 808's/KU 808 5.wav + src: /var/www/html/trens/src_mmpSearch/samples/imported/bassdrum_acoustic01_-_Copia.ogg stutter: '0' basenote: '57' fxch: '0' @@ -261106,7 +261105,7 @@ looped: '0' reversed: '0' sframe: '0' - src: Kid Urban Christmas BeatKit/Urban Percussion/KU Perc 10.wav + src: /var/www/html/trens/src_mmpSearch/samples/imported/bassdrum_acoustic02_-_Copia.ogg stutter: '0' basenote: '57' fxch: '0' @@ -261273,7 +261272,7 @@ looped: '0' reversed: '0' sframe: '0' - src: Kid Urban End Of The World BeatKit/EOTW Percussion/Kid Urban Perc 13.wav + src: /var/www/html/trens/src_mmpSearch/samples/imported/bassdrum_acoustic02_-_Copia.ogg stutter: '0' basenote: '57' fxch: '0' diff --git a/_data/drake.yml b/_data/drake.yml index f7bdb07d..c20900d4 100644 --- a/_data/drake.yml +++ b/_data/drake.yml @@ -177,8 +177,7 @@ tracks: looped: '0' reversed: '0' sframe: '0' - src: Young Kico - Chronicles Of The Atlantic Trap (Sound Kit) @YoungKico/01 - Kicks/Kick 1 (Layer With Any 808 For Authentic Zaytoven Delayed Kick).wav + src: /var/www/html/trens/src_mmpSearch/samples/imported/bassdrum_acoustic01_-_Copia.ogg stutter: '0' basenote: '57' fxch: '0' @@ -345,7 +344,7 @@ tracks: looped: '0' reversed: '0' sframe: '0' - src: lex_luger_drum_kit/lex_luger_drum_kit/LEX Rim(2).wav + src: /var/www/html/trens/src_mmpSearch/samples/imported/bassdrum_acoustic02_-_Copia.ogg stutter: '0' basenote: '57' fxch: '0' @@ -669,7 +668,7 @@ tracks: looped: '0' reversed: '0' sframe: '0' - src: Kid Urban Christmas BeatKit/Urban 808's/KU 808 5.wav + src: /var/www/html/trens/src_mmpSearch/samples/imported/bassdrum_acoustic01_-_Copia.ogg stutter: '0' basenote: '57' fxch: '0' @@ -836,7 +835,7 @@ tracks: looped: '0' reversed: '0' sframe: '0' - src: Kid Urban Christmas BeatKit/Urban Percussion/KU Perc 10.wav + src: /var/www/html/trens/src_mmpSearch/samples/imported/bassdrum_acoustic02_-_Copia.ogg stutter: '0' basenote: '57' fxch: '0' @@ -1003,7 +1002,7 @@ tracks: looped: '0' reversed: '0' sframe: '0' - src: Kid Urban End Of The World BeatKit/EOTW Percussion/Kid Urban Perc 13.wav + src: /var/www/html/trens/src_mmpSearch/samples/imported/bassdrum_acoustic02_-_Copia.ogg stutter: '0' basenote: '57' fxch: '0' diff --git a/_data/samples-manifest.json b/_data/samples-manifest.json index 24052094..73b00fcd 100644 --- a/_data/samples-manifest.json +++ b/_data/samples-manifest.json @@ -1,5 +1,8 @@ { "imported": { + "bassdrum_acoustic02_-_Copia.ogg": { + "_isFile": true + }, "bassdrum_acoustic01_-_Copia.ogg": { "_isFile": true } diff --git a/creation.html b/creation.html index bfe31e09..48acc97d 100755 --- a/creation.html +++ b/creation.html @@ -97,6 +97,8 @@ title="Salvar Projeto (.mmp)" > Salvar projeto + + Baixar ZIP + + diff --git a/scripts/handler/upload_server.py b/scripts/handler/upload_server.py index eccd265b..be0f2486 100755 --- a/scripts/handler/upload_server.py +++ b/scripts/handler/upload_server.py @@ -3,15 +3,15 @@ import subprocess import xml.etree.ElementTree as ET import gzip import zipfile -import zlib # <--- IMPORTANTE: Adicionado para suporte a mmpz raw +import zlib import json import shutil import time -from flask import Flask, request, jsonify +import io + +from flask import Flask, request, jsonify, send_file from flask_cors import CORS from werkzeug.utils import secure_filename - -# Importa suas funções e configurações existentes from main import process_single_file, rebuild_indexes, generate_manifests, slugify from utils import ALLOWED_EXTENSIONS, ALLOWED_SAMPLE_EXTENSIONS, MMP_FOLDER, MMPZ_FOLDER, CERT_PATH, KEY_PATH, BASE_DATA, SRC_MMPSEARCH, SAMPLE_SRC, METADATA_FOLDER, XML_IMPORTED_PATH_PREFIX, SAMPLE_MANIFEST @@ -217,6 +217,85 @@ def update_xml_paths_exact(mmp_filename, replacements): # --- ROTAS --- +@app.route("/api/download/", methods=["GET"]) +def download_project_package(project_name): + """ + Gera um ZIP contendo o arquivo .mmp e apenas os samples importados necessários. + Estrutura do ZIP: + - projeto.mmp + - src_mmpSearch/ + - samples/ + - imported/ + - sample1.wav + - sample2.wav + """ + # Garante que estamos pegando o .mmp (mesmo que peçam sem extensão) + if not project_name.endswith('.mmp'): + project_name += '.mmp' + + clean_name = secure_filename(project_name) + mmp_path = os.path.join(MMP_FOLDER, clean_name) + + if not os.path.exists(mmp_path): + return jsonify({"error": "Projeto não encontrado"}), 404 + + # Prepara o buffer do ZIP na memória (não salva no disco para economizar I/O) + memory_file = io.BytesIO() + + try: + with zipfile.ZipFile(memory_file, 'w', zipfile.ZIP_DEFLATED) as zf: + + # 1. Adiciona o arquivo .mmp na RAIZ do ZIP + # arcname é o nome que o arquivo terá dentro do zip + zf.write(mmp_path, arcname=clean_name) + + # 2. Lê o XML para descobrir quais samples incluir + tree = ET.parse(mmp_path) + root = tree.getroot() + + # Conjunto para evitar adicionar o mesmo sample 2x + samples_to_pack = set() + + for audio_node in root.findall(".//audiofileprocessor"): + src = audio_node.get('src', '') + + # Verifica se é um sample importado (nosso padrão) + # O src no XML já deve estar como: src_mmpSearch/samples/imported/nome.wav + if src.startswith(XML_IMPORTED_PATH_PREFIX): + # Extrai apenas o nome do arquivo (ex: kick.wav) + sample_filename = os.path.basename(src) + samples_to_pack.add(sample_filename) + + # 3. Adiciona os samples encontrados ao ZIP mantendo a estrutura de pasta + for sample_name in samples_to_pack: + # Caminho físico no servidor (onde o arquivo realmente está) + physical_path = os.path.join(PHYSICAL_IMPORTED_FOLDER, sample_name) + + # Caminho DENTRO do ZIP (para o LMMS ler relativo ao mmp) + # Deve ser: src_mmpSearch/samples/imported/sample.wav + zip_internal_path = f"{XML_IMPORTED_PATH_PREFIX}/{sample_name}" + + if os.path.exists(physical_path): + zf.write(physical_path, arcname=zip_internal_path) + print(f"[ZIP] Adicionado: {sample_name}") + else: + print(f"[ZIP] AVISO: Sample listado no XML mas não encontrado no disco: {sample_name}") + + # Finaliza o ponteiro do arquivo + memory_file.seek(0) + + return send_file( + memory_file, + mimetype='application/zip', + as_attachment=True, + download_name=f"{os.path.splitext(clean_name)[0]}_pack.zip" + ) + + except Exception as e: + import traceback + traceback.print_exc() + return jsonify({"error": f"Erro ao gerar pacote: {str(e)}"}), 500 + @app.route("/api/upload", methods=["POST"]) def upload_file(): if "project_file" not in request.files: