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: