launch-calcium commited on
Commit
52ad754
·
verified ·
1 Parent(s): 0dd525f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +20 -19
app.py CHANGED
@@ -4,9 +4,6 @@ Gradio app to convert one or more MIDI files into Geometry Dash .gmd files
4
  (using midi_to_gd.py). For each uploaded MIDI the app will create a .gmd
5
  file (plist wrapper with compressed k4 level string) and return a zip
6
  containing all generated .gmd files.
7
-
8
- Place this script in the same folder as midi_to_gd.py (or ensure the
9
- module is importable via PYTHONPATH).
10
  """
11
  import os
12
  import sys
@@ -15,7 +12,6 @@ import zipfile
15
  import traceback
16
  from typing import List, Tuple
17
 
18
- # Ensure the local module is importable
19
  HERE = os.path.dirname(os.path.abspath(__file__))
20
  if HERE not in sys.path:
21
  sys.path.insert(0, HERE)
@@ -39,15 +35,24 @@ except Exception as e:
39
 
40
  def _get_local_path_from_gr_file(f) -> str:
41
  """
42
- Gradio uploads can be either a path string or a file-like object with .name.
43
- This helper extracts the filesystem path.
 
 
 
44
  """
45
- if f is None:
46
  return ""
47
  if isinstance(f, str):
48
  return f
49
- # uploaded file object likely has .name attribute
50
- return getattr(f, "name", str(f))
 
 
 
 
 
 
51
 
52
 
53
  def convert_midis_to_zip(midi_files: List, beats_scale: float = 2.0, name_prefix: str = "") -> Tuple[str, str]:
@@ -65,23 +70,18 @@ def convert_midis_to_zip(midi_files: List, beats_scale: float = 2.0, name_prefix
65
  out_dir = tempfile.mkdtemp(prefix="gd_midis_")
66
  created_files = []
67
 
 
68
  for idx, f in enumerate(midi_files, start=1):
69
  midi_path = _get_local_path_from_gr_file(f)
70
- if not os.path.exists(midi_path):
71
- # Gradio might pass dicts in some versions; try to handle that
72
- if isinstance(f, dict) and "name" in f:
73
- midi_path = f["name"]
74
  if not os.path.exists(midi_path):
75
  return None, f"Uploaded file not found on disk: {midi_path}"
76
 
77
  base = os.path.splitext(os.path.basename(midi_path))[0]
78
  level_name = f"{name_prefix}{'_' if name_prefix else ''}{base}" if name_prefix else base
79
 
80
- # Parse MIDI and generate object string
81
  notes = parse_midi_notes(midi_path)
82
  raw_objects = generate_gd_level_objects(notes, blocks_per_beat=beats_scale)
83
 
84
- # Build compressed/encrypted k4 string and .gmd plist
85
  full_level_data = build_full_level_string(raw_objects)
86
  encrypted_k4 = encrypt_level_string(full_level_data)
87
 
@@ -101,7 +101,6 @@ def convert_midis_to_zip(midi_files: List, beats_scale: float = 2.0, name_prefix
101
  wf.write(gmd_content)
102
  created_files.append(out_path)
103
 
104
- # Create a zip containing all .gmd files
105
  zip_path = os.path.join(out_dir, "gd_levels.zip")
106
  with zipfile.ZipFile(zip_path, "w", compression=zipfile.ZIP_DEFLATED) as zf:
107
  for p in created_files:
@@ -128,7 +127,8 @@ def launch_ui():
128
  )
129
 
130
  with gr.Row():
131
- midi_input = gr.File(label="Upload MIDI files (.mid/.midi)", file_count="multiple", type="file")
 
132
  settings_col = gr.Column(scale=1)
133
  beats_scale = gr.Number(value=2.0, label="Blocks per beat (blocks/quarter-note)", precision=2)
134
  name_prefix = gr.Textbox(label="Optional level name prefix", placeholder="Prefix (optional)")
@@ -139,7 +139,6 @@ def launch_ui():
139
 
140
  def _on_click(files, beats, prefix):
141
  zip_path, status_text = convert_midis_to_zip(files, beats, prefix)
142
- # Gradio expects a file path to return for gr.File
143
  return zip_path, status_text
144
 
145
  convert_btn.click(fn=_on_click, inputs=[midi_input, beats_scale, name_prefix], outputs=[output_zip, status])
@@ -151,4 +150,6 @@ def launch_ui():
151
 
152
 
153
  if __name__ == "__main__":
154
- launch_ui()
 
 
 
4
  (using midi_to_gd.py). For each uploaded MIDI the app will create a .gmd
5
  file (plist wrapper with compressed k4 level string) and return a zip
6
  containing all generated .gmd files.
 
 
 
7
  """
8
  import os
9
  import sys
 
12
  import traceback
13
  from typing import List, Tuple
14
 
 
15
  HERE = os.path.dirname(os.path.abspath(__file__))
16
  if HERE not in sys.path:
17
  sys.path.insert(0, HERE)
 
35
 
36
  def _get_local_path_from_gr_file(f) -> str:
37
  """
38
+ Accepts the various shapes Gradio may pass:
39
+ - a filesystem path string
40
+ - a dict like {'name': '/tmp/....'}
41
+ - a list of the above (we only call this per-file)
42
+ Returns a single filesystem path string or empty if not found.
43
  """
44
+ if not f:
45
  return ""
46
  if isinstance(f, str):
47
  return f
48
+ if isinstance(f, (list, tuple)) and f:
49
+ # take first element
50
+ return _get_local_path_from_gr_file(f[0])
51
+ if isinstance(f, dict):
52
+ # Gradio sometimes returns {'name': '/tmp/...'}
53
+ return f.get("name") or f.get("file") or ""
54
+ # Fallback: try attribute .name
55
+ return getattr(f, "name", "")
56
 
57
 
58
  def convert_midis_to_zip(midi_files: List, beats_scale: float = 2.0, name_prefix: str = "") -> Tuple[str, str]:
 
70
  out_dir = tempfile.mkdtemp(prefix="gd_midis_")
71
  created_files = []
72
 
73
+ # midi_files is expected to be a list of file paths (type="filepath")
74
  for idx, f in enumerate(midi_files, start=1):
75
  midi_path = _get_local_path_from_gr_file(f)
 
 
 
 
76
  if not os.path.exists(midi_path):
77
  return None, f"Uploaded file not found on disk: {midi_path}"
78
 
79
  base = os.path.splitext(os.path.basename(midi_path))[0]
80
  level_name = f"{name_prefix}{'_' if name_prefix else ''}{base}" if name_prefix else base
81
 
 
82
  notes = parse_midi_notes(midi_path)
83
  raw_objects = generate_gd_level_objects(notes, blocks_per_beat=beats_scale)
84
 
 
85
  full_level_data = build_full_level_string(raw_objects)
86
  encrypted_k4 = encrypt_level_string(full_level_data)
87
 
 
101
  wf.write(gmd_content)
102
  created_files.append(out_path)
103
 
 
104
  zip_path = os.path.join(out_dir, "gd_levels.zip")
105
  with zipfile.ZipFile(zip_path, "w", compression=zipfile.ZIP_DEFLATED) as zf:
106
  for p in created_files:
 
127
  )
128
 
129
  with gr.Row():
130
+ # NOTE: type="filepath" is the correct modern API. 'file' is invalid.
131
+ midi_input = gr.File(label="Upload MIDI files (.mid/.midi)", file_count="multiple", type="filepath")
132
  settings_col = gr.Column(scale=1)
133
  beats_scale = gr.Number(value=2.0, label="Blocks per beat (blocks/quarter-note)", precision=2)
134
  name_prefix = gr.Textbox(label="Optional level name prefix", placeholder="Prefix (optional)")
 
139
 
140
  def _on_click(files, beats, prefix):
141
  zip_path, status_text = convert_midis_to_zip(files, beats, prefix)
 
142
  return zip_path, status_text
143
 
144
  convert_btn.click(fn=_on_click, inputs=[midi_input, beats_scale, name_prefix], outputs=[output_zip, status])
 
150
 
151
 
152
  if __name__ == "__main__":
153
+ launch_ui()
154
+
155
+