fix: GUI VST native window qua bridge + audio path bridge (SF2 preview/play câm)

- open_vst_gui: bo WebviewWindowBuilder/thread, chi push_control type=4 (hwnd=0 -> bridge tao window)
- main.cpp: create_native_vst_window (class SonicForge_Native_VST3_Class, 800x600, khong TOPMOST),
  tao trong ChannelWorker job, map guiWindows, capture arg2 by value (fix dangling)
- app.jsx: guard isBridgeActive() 8 cho -> bridge active thi moi note di router -> pushEvent -> bridge
  (truoc day SF2 cam vi HAS_PYFLUIDSYNTH=FALSE -> /soundfont-render 501; VST3 path cu dung nativeSf/Carla)
- E2E: SF2 NOTE_ON qua dispatchMidiEvent -> SHM peak 0.029745; Nexus GUI native hwnd OK (license/preset)
- docs: TASKS.md + TEST_NOTES.md ghi batch fix + ket qua; gitignore vendor/junk
This commit is contained in:
2026-08-12 22:12:43 +07:00
parent c3368d0a91
commit d8f8506077
37 changed files with 2170 additions and 419 deletions
+18 -8
View File
@@ -1232,14 +1232,20 @@ def _resolve_bridge_asset(name: str, instrument_type: str, path: Optional[str])
base = os.path.basename((path or name).replace("\\", "/"))
base_noext = os.path.splitext(base)[0].lower()
# sf2/sf3/sfz: storage/soundfonts + system + user plugin_dirs
for base_dir in [UPLOAD_SF_DIR, SYSTEM_SF_DIR]:
sf_dirs = [UPLOAD_SF_DIR, SYSTEM_SF_DIR]
try:
from app.core.vst_engine import _load_user_plugin_dirs
sf_dirs += _load_user_plugin_dirs() or []
except Exception:
pass
for base_dir in dict.fromkeys(d for d in sf_dirs if d):
if not os.path.isdir(base_dir):
continue
for fname in os.listdir(base_dir):
cand = os.path.join(base_dir, fname)
if fname.lower().endswith((".sf2", ".sf3", ".sfz")) and \
(fname.lower() == base.lower() or os.path.splitext(fname)[0].lower() == base_noext):
return cand
for root, _, files in os.walk(base_dir):
for fname in files:
if fname.lower().endswith((".sf2", ".sf3", ".sfz")) and \
(fname.lower() == base.lower() or os.path.splitext(fname)[0].lower() == base_noext):
return os.path.join(root, fname)
ext = (".vst3" if instrument_type.upper() == "VST3" else
".vst2" if instrument_type.upper() == "VST2" else
".sfz" if instrument_type.upper() == "SFZ" else None)
@@ -1249,8 +1255,12 @@ def _resolve_bridge_asset(name: str, instrument_type: str, path: Optional[str])
dirs = _load_user_plugin_dirs() or []
except Exception:
dirs = []
if not dirs:
dirs = [settings.VST_DIR, settings.SOUNDFONT_DIR]
# Luon gop VST_DIR/SOUNDFONT_DIR: neu chi dung user plugin_dirs,
# VST trong C:/Program Files/Common Files/VST3 khong resolve
# duoc -> bridge load fail -> VSTi cam / khong mo GUI.
for d in (settings.VST_DIR, settings.SOUNDFONT_DIR):
if d and d not in dirs:
dirs.append(d)
for base_dir in dirs:
if not os.path.isdir(base_dir):
continue