Spaces:
Running
on
Zero
Running
on
Zero
Delete gui-wx.py
Browse files
gui-wx.py
DELETED
@@ -1,635 +0,0 @@
|
|
1 |
-
import wx
|
2 |
-
import wx.adv
|
3 |
-
import wx.html
|
4 |
-
import wx.html2
|
5 |
-
import subprocess
|
6 |
-
import os
|
7 |
-
import threading
|
8 |
-
import queue
|
9 |
-
import json
|
10 |
-
import webbrowser
|
11 |
-
import requests
|
12 |
-
import sys
|
13 |
-
|
14 |
-
def run_subprocess(cmd, output_queue):
|
15 |
-
try:
|
16 |
-
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
|
17 |
-
for line in process.stdout:
|
18 |
-
output_queue.put(line)
|
19 |
-
process.wait()
|
20 |
-
if process.returncode == 0:
|
21 |
-
output_queue.put("Process completed successfully!")
|
22 |
-
else:
|
23 |
-
output_queue.put(f"Process failed with return code {process.returncode}")
|
24 |
-
except Exception as e:
|
25 |
-
output_queue.put(f"An error occurred: {str(e)}")
|
26 |
-
|
27 |
-
def update_output(output_text, output_queue):
|
28 |
-
try:
|
29 |
-
while True:
|
30 |
-
line = output_queue.get_nowait()
|
31 |
-
if wx.Window.FindWindowById(output_text.GetId()):
|
32 |
-
wx.CallAfter(output_text.AppendText, line)
|
33 |
-
else:
|
34 |
-
return # Exit if the text control no longer exists
|
35 |
-
except queue.Empty:
|
36 |
-
pass
|
37 |
-
except RuntimeError:
|
38 |
-
return # Exit if a RuntimeError occurs (e.g., window closed)
|
39 |
-
wx.CallLater(100, update_output, output_text, output_queue)
|
40 |
-
|
41 |
-
def open_store_folder(folder_path):
|
42 |
-
if os.path.exists(folder_path):
|
43 |
-
os.startfile(folder_path)
|
44 |
-
else:
|
45 |
-
wx.MessageBox(f"The folder {folder_path} does not exist.", "Error", wx.OK | wx.ICON_ERROR)
|
46 |
-
|
47 |
-
class DarkThemedTextCtrl(wx.TextCtrl):
|
48 |
-
def __init__(self, parent, id=wx.ID_ANY, value="", style=0):
|
49 |
-
super().__init__(parent, id, value, style=style | wx.NO_BORDER)
|
50 |
-
self.SetBackgroundColour(wx.Colour(0, 0, 0))
|
51 |
-
self.SetForegroundColour(wx.WHITE)
|
52 |
-
|
53 |
-
class CollapsiblePanel(wx.Panel):
|
54 |
-
def __init__(self, parent, title, *args, **kwargs):
|
55 |
-
wx.Panel.__init__(self, parent, *args, **kwargs)
|
56 |
-
self.SetBackgroundColour(parent.GetBackgroundColour())
|
57 |
-
|
58 |
-
self.toggle_button = wx.Button(self, label=title, style=wx.NO_BORDER)
|
59 |
-
self.toggle_button.SetBackgroundColour(self.GetBackgroundColour())
|
60 |
-
self.toggle_button.Bind(wx.EVT_BUTTON, self.on_toggle)
|
61 |
-
|
62 |
-
self.content_panel = wx.Panel(self)
|
63 |
-
self.content_panel.SetBackgroundColour(self.GetBackgroundColour())
|
64 |
-
|
65 |
-
self.main_sizer = wx.BoxSizer(wx.VERTICAL)
|
66 |
-
self.main_sizer.Add(self.toggle_button, 0, wx.EXPAND | wx.ALL, 5)
|
67 |
-
self.main_sizer.Add(self.content_panel, 0, wx.EXPAND | wx.ALL, 5)
|
68 |
-
|
69 |
-
self.SetSizer(self.main_sizer)
|
70 |
-
self.collapsed = True
|
71 |
-
self.toggle_button.SetLabel(f"▶ {title}")
|
72 |
-
self.content_panel.Hide()
|
73 |
-
|
74 |
-
def on_toggle(self, event):
|
75 |
-
self.collapsed = not self.collapsed
|
76 |
-
self.toggle_button.SetLabel(f"{'▶' if self.collapsed else '▼'} {self.toggle_button.GetLabel()[2:]}")
|
77 |
-
self.content_panel.Show(not self.collapsed)
|
78 |
-
self.Layout()
|
79 |
-
self.GetParent().Layout()
|
80 |
-
|
81 |
-
def get_content_panel(self):
|
82 |
-
return self.content_panel
|
83 |
-
|
84 |
-
class CustomToolTip(wx.PopupWindow):
|
85 |
-
def __init__(self, parent, text):
|
86 |
-
wx.PopupWindow.__init__(self, parent)
|
87 |
-
|
88 |
-
# Main panel for tooltip
|
89 |
-
panel = wx.Panel(self)
|
90 |
-
self.st = wx.StaticText(panel, 1, text, pos=(10, 10))
|
91 |
-
|
92 |
-
font = wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, "Poppins")
|
93 |
-
self.st.SetFont(font)
|
94 |
-
|
95 |
-
size = self.st.GetBestSize()
|
96 |
-
self.SetSize((size.width + 20, size.height + 20))
|
97 |
-
|
98 |
-
# Adjust the panel size
|
99 |
-
panel.SetSize(self.GetSize())
|
100 |
-
panel.SetBackgroundColour(wx.Colour(255, 255, 255))
|
101 |
-
|
102 |
-
# Bind paint event to draw border
|
103 |
-
panel.Bind(wx.EVT_PAINT, self.on_paint)
|
104 |
-
|
105 |
-
def on_paint(self, event):
|
106 |
-
# Get the device context for the panel (not self)
|
107 |
-
panel = event.GetEventObject() # Get the panel triggering the paint event
|
108 |
-
dc = wx.PaintDC(panel) # Use panel as the target of the PaintDC
|
109 |
-
dc.SetPen(wx.Pen(wx.Colour(210, 210, 210), 1)) # Border color
|
110 |
-
dc.SetBrush(wx.Brush(wx.Colour(255, 255, 255))) # Fill with white
|
111 |
-
|
112 |
-
size = panel.GetSize()
|
113 |
-
dc.DrawRectangle(0, 0, size.width, size.height) # Draw border around panel
|
114 |
-
|
115 |
-
class MainFrame(wx.Frame):
|
116 |
-
def __init__(self):
|
117 |
-
super().__init__(parent=None, title="Music Source Separation Training & Inference GUI")
|
118 |
-
self.SetSize(994, 670)
|
119 |
-
self.SetBackgroundColour(wx.Colour(247, 248, 250)) # #F7F8FA
|
120 |
-
|
121 |
-
icon = wx.Icon("gui/favicon.ico", wx.BITMAP_TYPE_ICO)
|
122 |
-
self.SetIcon(icon)
|
123 |
-
|
124 |
-
self.saved_combinations = {}
|
125 |
-
|
126 |
-
# Center the window on the screen
|
127 |
-
self.Center()
|
128 |
-
|
129 |
-
# Set Poppins font for the entire application
|
130 |
-
font_path = "gui/Poppins Regular 400.ttf"
|
131 |
-
bold_font_path = "gui/Poppins Bold 700.ttf"
|
132 |
-
wx.Font.AddPrivateFont(font_path)
|
133 |
-
wx.Font.AddPrivateFont(bold_font_path)
|
134 |
-
self.font = wx.Font(9, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, "Poppins")
|
135 |
-
self.bold_font = wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, "Poppins")
|
136 |
-
self.SetFont(self.font)
|
137 |
-
|
138 |
-
panel = wx.Panel(self)
|
139 |
-
main_sizer = wx.BoxSizer(wx.VERTICAL)
|
140 |
-
|
141 |
-
# Add image (with error handling)
|
142 |
-
try:
|
143 |
-
img = wx.Image("gui/mvsep.png", wx.BITMAP_TYPE_PNG)
|
144 |
-
img_bitmap = wx.Bitmap(img)
|
145 |
-
img_ctrl = wx.StaticBitmap(panel, -1, img_bitmap)
|
146 |
-
main_sizer.Add(img_ctrl, 0, wx.ALIGN_CENTER | wx.TOP, 20)
|
147 |
-
except:
|
148 |
-
print("Failed to load image: gui/mvsep.png")
|
149 |
-
|
150 |
-
# Add title text
|
151 |
-
title_text = wx.StaticText(panel, label="Music Source Separation Training && Inference GUI")
|
152 |
-
title_text.SetFont(self.bold_font)
|
153 |
-
title_text.SetForegroundColour(wx.BLACK)
|
154 |
-
main_sizer.Add(title_text, 0, wx.ALIGN_CENTER | wx.TOP, 10)
|
155 |
-
|
156 |
-
# Add subtitle text
|
157 |
-
subtitle_text = wx.StaticText(panel, label="Code by ZFTurbo / GUI by Bas Curtiz")
|
158 |
-
subtitle_text.SetForegroundColour(wx.BLACK)
|
159 |
-
main_sizer.Add(subtitle_text, 0, wx.ALIGN_CENTER | wx.TOP, 5)
|
160 |
-
|
161 |
-
# Add GitHub link
|
162 |
-
github_link = wx.adv.HyperlinkCtrl(panel, -1, "GitHub Repository", "https://github.com/ZFTurbo/Music-Source-Separation-Training")
|
163 |
-
github_link.SetNormalColour(wx.Colour(1, 118, 179)) # #0176B3
|
164 |
-
github_link.SetHoverColour(wx.Colour(86, 91, 123)) # #565B7B
|
165 |
-
main_sizer.Add(github_link, 0, wx.ALIGN_CENTER | wx.TOP, 10)
|
166 |
-
|
167 |
-
# Add Download models button on a new line with 10px bottom margin
|
168 |
-
download_models_btn = self.create_styled_button(panel, "Download Models", self.on_download_models)
|
169 |
-
main_sizer.Add(download_models_btn, 0, wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM, 10)
|
170 |
-
|
171 |
-
# Training Configuration
|
172 |
-
self.training_panel = CollapsiblePanel(panel, "Training Configuration")
|
173 |
-
self.training_panel.toggle_button.SetFont(self.bold_font)
|
174 |
-
self.create_training_controls(self.training_panel.get_content_panel())
|
175 |
-
main_sizer.Add(self.training_panel, 0, wx.EXPAND | wx.ALL, 10)
|
176 |
-
|
177 |
-
# Inference Configuration
|
178 |
-
self.inference_panel = CollapsiblePanel(panel, "Inference Configuration")
|
179 |
-
self.inference_panel.toggle_button.SetFont(self.bold_font)
|
180 |
-
self.create_inference_controls(self.inference_panel.get_content_panel())
|
181 |
-
main_sizer.Add(self.inference_panel, 0, wx.EXPAND | wx.ALL, 10)
|
182 |
-
|
183 |
-
panel.SetSizer(main_sizer)
|
184 |
-
self.load_settings()
|
185 |
-
|
186 |
-
def create_styled_button(self, parent, label, handler):
|
187 |
-
btn = wx.Button(parent, label=label, style=wx.BORDER_NONE)
|
188 |
-
btn.SetBackgroundColour(wx.Colour(1, 118, 179)) # #0176B3
|
189 |
-
btn.SetForegroundColour(wx.WHITE)
|
190 |
-
btn.SetFont(self.bold_font)
|
191 |
-
|
192 |
-
def on_enter(event):
|
193 |
-
btn.SetBackgroundColour(wx.Colour(86, 91, 123))
|
194 |
-
event.Skip()
|
195 |
-
|
196 |
-
def on_leave(event):
|
197 |
-
btn.SetBackgroundColour(wx.Colour(1, 118, 179))
|
198 |
-
event.Skip()
|
199 |
-
|
200 |
-
def on_click(event):
|
201 |
-
btn.SetBackgroundColour(wx.Colour(86, 91, 123))
|
202 |
-
handler(event)
|
203 |
-
wx.CallLater(100, lambda: btn.SetBackgroundColour(wx.Colour(1, 118, 179)))
|
204 |
-
|
205 |
-
btn.Bind(wx.EVT_ENTER_WINDOW, on_enter)
|
206 |
-
btn.Bind(wx.EVT_LEAVE_WINDOW, on_leave)
|
207 |
-
btn.Bind(wx.EVT_BUTTON, on_click)
|
208 |
-
|
209 |
-
return btn
|
210 |
-
|
211 |
-
def create_training_controls(self, panel):
|
212 |
-
sizer = wx.BoxSizer(wx.VERTICAL)
|
213 |
-
|
214 |
-
# Model Type
|
215 |
-
model_type_sizer = wx.BoxSizer(wx.HORIZONTAL)
|
216 |
-
model_type_sizer.Add(wx.StaticText(panel, label="Model Type:"), 0, wx.ALIGN_CENTER_VERTICAL)
|
217 |
-
self.model_type = wx.Choice(panel, choices=["apollo", "bandit", "bandit_v2", "bs_roformer", "htdemucs", "mdx23c", "mel_band_roformer", "scnet", "scnet_unofficial", "segm_models", "swin_upernet", "torchseg"])
|
218 |
-
self.model_type.SetFont(self.font)
|
219 |
-
model_type_sizer.Add(self.model_type, 0, wx.LEFT, 5)
|
220 |
-
sizer.Add(model_type_sizer, 0, wx.EXPAND | wx.ALL, 5)
|
221 |
-
|
222 |
-
# Config File
|
223 |
-
self.config_entry = self.add_browse_control(panel, sizer, "Config File:", is_folder=False, is_config=True)
|
224 |
-
|
225 |
-
# Start Checkpoint
|
226 |
-
self.checkpoint_entry = self.add_browse_control(panel, sizer, "Checkpoint:", is_folder=False, is_checkpoint=True)
|
227 |
-
|
228 |
-
# Results Path
|
229 |
-
self.result_path_entry = self.add_browse_control(panel, sizer, "Results Path:", is_folder=True)
|
230 |
-
|
231 |
-
# Data Paths
|
232 |
-
self.data_entry = self.add_browse_control(panel, sizer, "Data Paths (separated by ';'):", is_folder=True)
|
233 |
-
|
234 |
-
# Validation Paths
|
235 |
-
self.valid_entry = self.add_browse_control(panel, sizer, "Validation Paths (separated by ';'):", is_folder=True)
|
236 |
-
|
237 |
-
# Number of Workers and Device IDs
|
238 |
-
workers_device_sizer = wx.BoxSizer(wx.HORIZONTAL)
|
239 |
-
|
240 |
-
workers_sizer = wx.BoxSizer(wx.HORIZONTAL)
|
241 |
-
workers_sizer.Add(wx.StaticText(panel, label="Number of Workers:"), 0, wx.ALIGN_CENTER_VERTICAL)
|
242 |
-
self.workers_entry = wx.TextCtrl(panel, value="4")
|
243 |
-
self.workers_entry.SetFont(self.font)
|
244 |
-
workers_sizer.Add(self.workers_entry, 0, wx.LEFT, 5)
|
245 |
-
workers_device_sizer.Add(workers_sizer, 0, wx.EXPAND)
|
246 |
-
|
247 |
-
device_sizer = wx.BoxSizer(wx.HORIZONTAL)
|
248 |
-
device_sizer.Add(wx.StaticText(panel, label="Device IDs (comma-separated):"), 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 20)
|
249 |
-
self.device_entry = wx.TextCtrl(panel, value="0")
|
250 |
-
self.device_entry.SetFont(self.font)
|
251 |
-
device_sizer.Add(self.device_entry, 0, wx.LEFT, 5)
|
252 |
-
workers_device_sizer.Add(device_sizer, 0, wx.EXPAND)
|
253 |
-
|
254 |
-
sizer.Add(workers_device_sizer, 0, wx.EXPAND | wx.ALL, 5)
|
255 |
-
|
256 |
-
# Run Training Button
|
257 |
-
self.run_button = self.create_styled_button(panel, "Run Training", self.run_training)
|
258 |
-
sizer.Add(self.run_button, 0, wx.ALIGN_CENTER | wx.ALL, 10)
|
259 |
-
|
260 |
-
panel.SetSizer(sizer)
|
261 |
-
|
262 |
-
def create_inference_controls(self, panel):
|
263 |
-
sizer = wx.BoxSizer(wx.VERTICAL)
|
264 |
-
|
265 |
-
# Model Type and Saved Combinations
|
266 |
-
infer_model_type_sizer = wx.BoxSizer(wx.HORIZONTAL)
|
267 |
-
infer_model_type_sizer.Add(wx.StaticText(panel, label="Model Type:"), 0, wx.ALIGN_CENTER_VERTICAL)
|
268 |
-
self.infer_model_type = wx.Choice(panel, choices=["apollo", "bandit", "bandit_v2", "bs_roformer", "htdemucs", "mdx23c", "mel_band_roformer", "scnet", "scnet_unofficial", "segm_models", "swin_upernet", "torchseg"])
|
269 |
-
self.infer_model_type.SetFont(self.font)
|
270 |
-
infer_model_type_sizer.Add(self.infer_model_type, 0, wx.LEFT, 5)
|
271 |
-
|
272 |
-
# Add "Preset:" label
|
273 |
-
infer_model_type_sizer.Add(wx.StaticText(panel, label="Preset:"), 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 20)
|
274 |
-
|
275 |
-
# Add dropdown for saved combinations
|
276 |
-
self.saved_combinations_dropdown = wx.Choice(panel, choices=[])
|
277 |
-
self.saved_combinations_dropdown.SetFont(self.font)
|
278 |
-
self.saved_combinations_dropdown.Bind(wx.EVT_CHOICE, self.on_combination_selected)
|
279 |
-
|
280 |
-
# Set the width to 200px and an appropriate height
|
281 |
-
self.saved_combinations_dropdown.SetMinSize((358, -1)) # -1 keeps the height unchanged
|
282 |
-
|
283 |
-
# Add to sizer
|
284 |
-
infer_model_type_sizer.Add(self.saved_combinations_dropdown, 0, wx.LEFT, 5)
|
285 |
-
|
286 |
-
# Add plus button
|
287 |
-
plus_button = self.create_styled_button(panel, "+", self.on_save_combination)
|
288 |
-
plus_button.SetMinSize((30, 30))
|
289 |
-
infer_model_type_sizer.Add(plus_button, 0, wx.LEFT, 5)
|
290 |
-
|
291 |
-
# Add help button with custom tooltip
|
292 |
-
help_button = wx.StaticText(panel, label="?")
|
293 |
-
help_button.SetFont(self.bold_font)
|
294 |
-
help_button.SetForegroundColour(wx.Colour(1, 118, 179)) #0176B3
|
295 |
-
tooltip_text = ("How to add a preset?\n\n"
|
296 |
-
"1. Click Download Models\n"
|
297 |
-
"2. Right-click a model's Config && Checkpoint\n"
|
298 |
-
"3. Save link as && select a proper destination\n"
|
299 |
-
"4. Copy the Model name\n"
|
300 |
-
"5. Close Download Models\n\n"
|
301 |
-
"6. Browse for the Config file\n"
|
302 |
-
"7. Browse for the Checkpoint\n"
|
303 |
-
"8. Select the Model Type\n"
|
304 |
-
"9. Click the + button\n"
|
305 |
-
"10. Paste the Model name && click OK\n\n"
|
306 |
-
"On next use, just select it from the Preset dropdown.")
|
307 |
-
|
308 |
-
self.tooltip = CustomToolTip(self, tooltip_text)
|
309 |
-
self.tooltip.Hide()
|
310 |
-
|
311 |
-
def on_help_enter(event):
|
312 |
-
self.tooltip.Position(help_button.ClientToScreen((0, help_button.GetSize().height)), (0, 0))
|
313 |
-
self.tooltip.Show()
|
314 |
-
|
315 |
-
def on_help_leave(event):
|
316 |
-
self.tooltip.Hide()
|
317 |
-
|
318 |
-
help_button.Bind(wx.EVT_ENTER_WINDOW, on_help_enter)
|
319 |
-
help_button.Bind(wx.EVT_LEAVE_WINDOW, on_help_leave)
|
320 |
-
|
321 |
-
infer_model_type_sizer.Add(help_button, 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 5)
|
322 |
-
|
323 |
-
sizer.Add(infer_model_type_sizer, 0, wx.EXPAND | wx.ALL, 5)
|
324 |
-
|
325 |
-
# Config File
|
326 |
-
self.infer_config_entry = self.add_browse_control(panel, sizer, "Config File:", is_folder=False, is_config=True)
|
327 |
-
|
328 |
-
# Start Checkpoint
|
329 |
-
self.infer_checkpoint_entry = self.add_browse_control(panel, sizer, "Checkpoint:", is_folder=False, is_checkpoint=True)
|
330 |
-
|
331 |
-
# Input Folder
|
332 |
-
self.infer_input_entry = self.add_browse_control(panel, sizer, "Input Folder:", is_folder=True)
|
333 |
-
|
334 |
-
# Store Directory
|
335 |
-
self.infer_store_entry = self.add_browse_control(panel, sizer, "Output Folder:", is_folder=True)
|
336 |
-
|
337 |
-
# Extract Instrumental Checkbox
|
338 |
-
self.extract_instrumental_checkbox = wx.CheckBox(panel, label="Extract Instrumental")
|
339 |
-
self.extract_instrumental_checkbox.SetFont(self.font)
|
340 |
-
sizer.Add(self.extract_instrumental_checkbox, 0, wx.EXPAND | wx.ALL, 5)
|
341 |
-
|
342 |
-
# Run Inference Button
|
343 |
-
self.run_infer_button = self.create_styled_button(panel, "Run Inference", self.run_inference)
|
344 |
-
sizer.Add(self.run_infer_button, 0, wx.ALIGN_CENTER | wx.ALL, 10)
|
345 |
-
|
346 |
-
panel.SetSizer(sizer)
|
347 |
-
|
348 |
-
def add_browse_control(self, panel, sizer, label, is_folder=False, is_config=False, is_checkpoint=False):
|
349 |
-
browse_sizer = wx.BoxSizer(wx.HORIZONTAL)
|
350 |
-
browse_sizer.Add(wx.StaticText(panel, label=label), 0, wx.ALIGN_CENTER_VERTICAL)
|
351 |
-
entry = wx.TextCtrl(panel)
|
352 |
-
entry.SetFont(self.font)
|
353 |
-
browse_sizer.Add(entry, 1, wx.EXPAND | wx.LEFT, 5)
|
354 |
-
browse_button = self.create_styled_button(panel, "Browse", lambda event, entry=entry, is_folder=is_folder, is_config=is_config, is_checkpoint=is_checkpoint: self.browse(event, entry, is_folder, is_config, is_checkpoint))
|
355 |
-
browse_sizer.Add(browse_button, 0, wx.LEFT, 5)
|
356 |
-
sizer.Add(browse_sizer, 0, wx.EXPAND | wx.ALL, 5)
|
357 |
-
return entry
|
358 |
-
|
359 |
-
def browse(self, event, entry, is_folder=False, is_config=False, is_checkpoint=False):
|
360 |
-
if is_folder:
|
361 |
-
dialog = wx.DirDialog(self, "Choose a directory", style=wx.DD_DEFAULT_STYLE | wx.DD_DIR_MUST_EXIST)
|
362 |
-
else:
|
363 |
-
wildcard = "All files (*.*)|*.*"
|
364 |
-
if is_config:
|
365 |
-
wildcard = "YAML files (*.yaml)|*.yaml"
|
366 |
-
elif is_checkpoint:
|
367 |
-
wildcard = "Checkpoint files (*.bin;*.chpt;*.ckpt;*.th)|*.bin;*.chpt;*.ckpt;*.th"
|
368 |
-
|
369 |
-
dialog = wx.FileDialog(self, "Choose a file", style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST, wildcard=wildcard)
|
370 |
-
|
371 |
-
dialog.SetFont(self.font)
|
372 |
-
if dialog.ShowModal() == wx.ID_OK:
|
373 |
-
entry.SetValue(dialog.GetPath())
|
374 |
-
dialog.Destroy()
|
375 |
-
|
376 |
-
def create_output_window(self, title, folder_path):
|
377 |
-
output_frame = wx.Frame(self, title=title, style=wx.DEFAULT_FRAME_STYLE | wx.STAY_ON_TOP)
|
378 |
-
output_frame.SetIcon(self.GetIcon())
|
379 |
-
output_frame.SetSize(994, 670)
|
380 |
-
output_frame.SetBackgroundColour(wx.Colour(0, 0, 0))
|
381 |
-
output_frame.SetFont(self.font)
|
382 |
-
|
383 |
-
# Set the position of the output frame to match the main frame
|
384 |
-
output_frame.SetPosition(self.GetPosition())
|
385 |
-
|
386 |
-
output_title = wx.StaticText(output_frame, label=title)
|
387 |
-
output_title.SetFont(self.bold_font)
|
388 |
-
output_title.SetForegroundColour(wx.WHITE)
|
389 |
-
|
390 |
-
output_text = DarkThemedTextCtrl(output_frame, style=wx.TE_MULTILINE | wx.TE_READONLY)
|
391 |
-
output_text.SetFont(self.font)
|
392 |
-
|
393 |
-
open_folder_button = self.create_styled_button(output_frame, f"Open Output Folder", lambda event: open_store_folder(folder_path))
|
394 |
-
|
395 |
-
sizer = wx.BoxSizer(wx.VERTICAL)
|
396 |
-
sizer.Add(output_title, 0, wx.ALIGN_CENTER | wx.TOP, 10)
|
397 |
-
sizer.Add(output_text, 1, wx.EXPAND | wx.ALL, 10)
|
398 |
-
sizer.Add(open_folder_button, 0, wx.ALIGN_CENTER | wx.BOTTOM, 10)
|
399 |
-
output_frame.SetSizer(sizer)
|
400 |
-
|
401 |
-
return output_frame, output_text
|
402 |
-
|
403 |
-
def run_training(self, event):
|
404 |
-
model_type = self.model_type.GetStringSelection()
|
405 |
-
config_path = self.config_entry.GetValue()
|
406 |
-
start_checkpoint = self.checkpoint_entry.GetValue()
|
407 |
-
results_path = self.result_path_entry.GetValue()
|
408 |
-
data_paths = self.data_entry.GetValue()
|
409 |
-
valid_paths = self.valid_entry.GetValue()
|
410 |
-
num_workers = self.workers_entry.GetValue()
|
411 |
-
device_ids = self.device_entry.GetValue()
|
412 |
-
|
413 |
-
if not model_type:
|
414 |
-
wx.MessageBox("Please select a model type.", "Input Error", wx.OK | wx.ICON_ERROR)
|
415 |
-
return
|
416 |
-
if not config_path:
|
417 |
-
wx.MessageBox("Please select a config file.", "Input Error", wx.OK | wx.ICON_ERROR)
|
418 |
-
return
|
419 |
-
if not results_path:
|
420 |
-
wx.MessageBox("Please specify a results path.", "Input Error", wx.OK | wx.ICON_ERROR)
|
421 |
-
return
|
422 |
-
if not data_paths:
|
423 |
-
wx.MessageBox("Please specify data paths.", "Input Error", wx.OK | wx.ICON_ERROR)
|
424 |
-
return
|
425 |
-
if not valid_paths:
|
426 |
-
wx.MessageBox("Please specify validation paths.", "Input Error", wx.OK | wx.ICON_ERROR)
|
427 |
-
return
|
428 |
-
|
429 |
-
cmd = [
|
430 |
-
sys.executable, "train.py",
|
431 |
-
"--model_type", model_type,
|
432 |
-
"--config_path", config_path,
|
433 |
-
"--results_path", results_path,
|
434 |
-
"--data_path", *data_paths.split(';'),
|
435 |
-
"--valid_path", *valid_paths.split(';'),
|
436 |
-
"--num_workers", num_workers,
|
437 |
-
"--device_ids", device_ids
|
438 |
-
]
|
439 |
-
|
440 |
-
if start_checkpoint:
|
441 |
-
cmd += ["--start_check_point", start_checkpoint]
|
442 |
-
|
443 |
-
output_queue = queue.Queue()
|
444 |
-
threading.Thread(target=run_subprocess, args=(cmd, output_queue), daemon=True).start()
|
445 |
-
|
446 |
-
output_frame, output_text = self.create_output_window("Training Output", results_path)
|
447 |
-
output_frame.Show()
|
448 |
-
update_output(output_text, output_queue)
|
449 |
-
|
450 |
-
self.save_settings()
|
451 |
-
|
452 |
-
def run_inference(self, event):
|
453 |
-
model_type = self.infer_model_type.GetStringSelection()
|
454 |
-
config_path = self.infer_config_entry.GetValue()
|
455 |
-
start_checkpoint = self.infer_checkpoint_entry.GetValue()
|
456 |
-
input_folder = self.infer_input_entry.GetValue()
|
457 |
-
store_dir = self.infer_store_entry.GetValue()
|
458 |
-
extract_instrumental = self.extract_instrumental_checkbox.GetValue()
|
459 |
-
|
460 |
-
if not model_type:
|
461 |
-
wx.MessageBox("Please select a model type.", "Input Error", wx.OK | wx.ICON_ERROR)
|
462 |
-
return
|
463 |
-
if not config_path:
|
464 |
-
wx.MessageBox("Please select a config file.", "Input Error", wx.OK | wx.ICON_ERROR)
|
465 |
-
return
|
466 |
-
if not input_folder:
|
467 |
-
wx.MessageBox("Please specify an input folder.", "Input Error", wx.OK | wx.ICON_ERROR)
|
468 |
-
return
|
469 |
-
if not store_dir:
|
470 |
-
wx.MessageBox("Please specify an output folder.", "Input Error", wx.OK | wx.ICON_ERROR)
|
471 |
-
return
|
472 |
-
|
473 |
-
cmd = [
|
474 |
-
sys.executable, "inference.py",
|
475 |
-
"--model_type", model_type,
|
476 |
-
"--config_path", config_path,
|
477 |
-
"--input_folder", input_folder,
|
478 |
-
"--store_dir", store_dir
|
479 |
-
]
|
480 |
-
|
481 |
-
if start_checkpoint:
|
482 |
-
cmd += ["--start_check_point", start_checkpoint]
|
483 |
-
|
484 |
-
if extract_instrumental:
|
485 |
-
cmd += ["--extract_instrumental"]
|
486 |
-
|
487 |
-
output_queue = queue.Queue()
|
488 |
-
threading.Thread(target=run_subprocess, args=(cmd, output_queue), daemon=True).start()
|
489 |
-
|
490 |
-
output_frame, output_text = self.create_output_window("Inference Output", store_dir)
|
491 |
-
output_frame.Show()
|
492 |
-
update_output(output_text, output_queue)
|
493 |
-
|
494 |
-
self.save_settings()
|
495 |
-
|
496 |
-
def save_settings(self):
|
497 |
-
settings = {
|
498 |
-
"model_type": self.model_type.GetStringSelection(),
|
499 |
-
"config_path": self.config_entry.GetValue(),
|
500 |
-
"start_checkpoint": self.checkpoint_entry.GetValue(),
|
501 |
-
"results_path": self.result_path_entry.GetValue(),
|
502 |
-
"data_paths": self.data_entry.GetValue(),
|
503 |
-
"valid_paths": self.valid_entry.GetValue(),
|
504 |
-
"num_workers": self.workers_entry.GetValue(),
|
505 |
-
"device_ids": self.device_entry.GetValue(),
|
506 |
-
"infer_model_type": self.infer_model_type.GetStringSelection(),
|
507 |
-
"infer_config_path": self.infer_config_entry.GetValue(),
|
508 |
-
"infer_start_checkpoint": self.infer_checkpoint_entry.GetValue(),
|
509 |
-
"infer_input_folder": self.infer_input_entry.GetValue(),
|
510 |
-
"infer_store_dir": self.infer_store_entry.GetValue(),
|
511 |
-
"extract_instrumental": self.extract_instrumental_checkbox.GetValue(),
|
512 |
-
"saved_combinations": self.saved_combinations
|
513 |
-
}
|
514 |
-
with open("settings.json", "w") as f:
|
515 |
-
json.dump(settings, f, indent=2, ensure_ascii=False)
|
516 |
-
|
517 |
-
def load_settings(self):
|
518 |
-
try:
|
519 |
-
with open("settings.json", "r") as f:
|
520 |
-
settings = json.load(f)
|
521 |
-
|
522 |
-
self.model_type.SetStringSelection(settings.get("model_type", ""))
|
523 |
-
self.config_entry.SetValue(settings.get("config_path", ""))
|
524 |
-
self.checkpoint_entry.SetValue(settings.get("start_checkpoint", ""))
|
525 |
-
self.result_path_entry.SetValue(settings.get("results_path", ""))
|
526 |
-
self.data_entry.SetValue(settings.get("data_paths", ""))
|
527 |
-
self.valid_entry.SetValue(settings.get("valid_paths", ""))
|
528 |
-
self.workers_entry.SetValue(settings.get("num_workers", "4"))
|
529 |
-
self.device_entry.SetValue(settings.get("device_ids", "0"))
|
530 |
-
|
531 |
-
self.infer_model_type.SetStringSelection(settings.get("infer_model_type", ""))
|
532 |
-
self.infer_config_entry.SetValue(settings.get("infer_config_path", ""))
|
533 |
-
self.infer_checkpoint_entry.SetValue(settings.get("infer_start_checkpoint", ""))
|
534 |
-
self.infer_input_entry.SetValue(settings.get("infer_input_folder", ""))
|
535 |
-
self.infer_store_entry.SetValue(settings.get("infer_store_dir", ""))
|
536 |
-
self.extract_instrumental_checkbox.SetValue(settings.get("extract_instrumental", False))
|
537 |
-
self.saved_combinations = settings.get("saved_combinations", {})
|
538 |
-
|
539 |
-
self.update_saved_combinations()
|
540 |
-
except FileNotFoundError:
|
541 |
-
pass # If the settings file doesn't exist, use default values
|
542 |
-
|
543 |
-
def on_download_models(self, event):
|
544 |
-
DownloadModelsFrame(self).Show()
|
545 |
-
|
546 |
-
def on_save_combination(self, event):
|
547 |
-
dialog = wx.TextEntryDialog(self, "Enter a name for this preset:", "Save Preset")
|
548 |
-
if dialog.ShowModal() == wx.ID_OK:
|
549 |
-
name = dialog.GetValue()
|
550 |
-
if name:
|
551 |
-
combination = {
|
552 |
-
"model_type": self.infer_model_type.GetStringSelection(),
|
553 |
-
"config_path": self.infer_config_entry.GetValue(),
|
554 |
-
"checkpoint": self.infer_checkpoint_entry.GetValue()
|
555 |
-
}
|
556 |
-
self.saved_combinations[name] = combination
|
557 |
-
self.update_saved_combinations()
|
558 |
-
self.save_settings()
|
559 |
-
dialog.Destroy()
|
560 |
-
|
561 |
-
def on_combination_selected(self, event):
|
562 |
-
name = self.saved_combinations_dropdown.GetStringSelection()
|
563 |
-
if name:
|
564 |
-
combination = self.saved_combinations.get(name)
|
565 |
-
if combination:
|
566 |
-
self.infer_model_type.SetStringSelection(combination["model_type"])
|
567 |
-
self.infer_config_entry.SetValue(combination["config_path"])
|
568 |
-
self.infer_checkpoint_entry.SetValue(combination["checkpoint"])
|
569 |
-
|
570 |
-
def update_saved_combinations(self):
|
571 |
-
self.saved_combinations_dropdown.Clear()
|
572 |
-
for name in self.saved_combinations.keys():
|
573 |
-
self.saved_combinations_dropdown.Append(name)
|
574 |
-
|
575 |
-
class DownloadModelsFrame(wx.Frame):
|
576 |
-
def __init__(self, parent):
|
577 |
-
super().__init__(parent, title="Download Models", size=(994, 670), style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX))
|
578 |
-
self.SetBackgroundColour(wx.Colour(247, 248, 250)) # #F7F8FA
|
579 |
-
self.SetFont(wx.Font(9, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, "Poppins"))
|
580 |
-
|
581 |
-
# Set the position of the Download Models frame to match the main frame
|
582 |
-
self.SetPosition(parent.GetPosition())
|
583 |
-
|
584 |
-
# Set the icon for the Download Models frame
|
585 |
-
icon = wx.Icon("gui/favicon.ico", wx.BITMAP_TYPE_ICO)
|
586 |
-
self.SetIcon(icon)
|
587 |
-
|
588 |
-
panel = wx.Panel(self)
|
589 |
-
sizer = wx.BoxSizer(wx.VERTICAL)
|
590 |
-
|
591 |
-
# Add WebView
|
592 |
-
self.web_view = wx.html2.WebView.New(panel)
|
593 |
-
self.web_view.LoadURL("https://bascurtiz.x10.mx/models-checkpoint-config-urls.html")
|
594 |
-
self.web_view.Bind(wx.html2.EVT_WEBVIEW_NAVIGATING, self.on_link_click)
|
595 |
-
self.web_view.Bind(wx.html2.EVT_WEBVIEW_NAVIGATED, self.on_page_load)
|
596 |
-
sizer.Add(self.web_view, 1, wx.EXPAND)
|
597 |
-
|
598 |
-
panel.SetSizer(sizer)
|
599 |
-
|
600 |
-
def on_link_click(self, event):
|
601 |
-
url = event.GetURL()
|
602 |
-
if not url.startswith("https://bascurtiz.x10.mx"):
|
603 |
-
event.Veto() # Prevent the WebView from navigating
|
604 |
-
webbrowser.open(url) # Open the link in the default browser
|
605 |
-
|
606 |
-
def on_page_load(self, event):
|
607 |
-
self.inject_custom_css()
|
608 |
-
|
609 |
-
def inject_custom_css(self):
|
610 |
-
css = """
|
611 |
-
body {
|
612 |
-
margin: 0;
|
613 |
-
padding: 0;
|
614 |
-
}
|
615 |
-
::-webkit-scrollbar {
|
616 |
-
width: 12px;
|
617 |
-
}
|
618 |
-
::-webkit-scrollbar-track {
|
619 |
-
background: #f1f1f1;
|
620 |
-
}
|
621 |
-
::-webkit-scrollbar-thumb {
|
622 |
-
background: #888;
|
623 |
-
}
|
624 |
-
::-webkit-scrollbar-thumb:hover {
|
625 |
-
background: #555;
|
626 |
-
}
|
627 |
-
"""
|
628 |
-
js = f"var style = document.createElement('style'); style.textContent = `{css}`; document.head.appendChild(style);"
|
629 |
-
self.web_view.RunScript(js)
|
630 |
-
|
631 |
-
if __name__ == "__main__":
|
632 |
-
app = wx.App()
|
633 |
-
frame = MainFrame()
|
634 |
-
frame.Show()
|
635 |
-
app.MainLoop()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|