From a8082b27c45f6109b969efe80bbdd9a0711cb66a Mon Sep 17 00:00:00 2001 From: locpham Date: Tue, 1 Sep 2026 10:37:12 +0700 Subject: [PATCH] =?UTF-8?q?V45.33:=20fix=20Plugin=20Manager=20VSTi=20li?= =?UTF-8?q?=E1=BB=87t=20k=C3=AA=20nh=E1=BA=A7m=20VST=20FX=20(Ozone=20Pro/T?= =?UTF-8?q?onal=20Balance=20Control=20Pro)=20l=C3=A0m=20instrument=20-=20/?= =?UTF-8?q?available=20ch=E1=BA=B7n=20entry=20UNKNOWN=20theo=20t=C3=AAn=20?= =?UTF-8?q?(bridge=20timeout=20introspect=20VST3)=20+=20=5Fnorm=5Fpath=5Fs?= =?UTF-8?q?tem?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/v1/plugins.py | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/app/api/v1/plugins.py b/app/api/v1/plugins.py index 0e82d71..52716c6 100644 --- a/app/api/v1/plugins.py +++ b/app/api/v1/plugins.py @@ -210,6 +210,7 @@ async def list_plugins(current_user: dict = Depends(get_current_user)): fx_paths = set() unknown_paths = set() fx_norm_names = set() + unknown_norm_names = set() try: from app.core.vst_engine import get_plugin_manager for e in get_plugin_manager().list_scan_all(): @@ -217,8 +218,11 @@ async def list_plugins(current_user: dict = Depends(get_current_user)): if e.get("is_fx"): fx_paths.add(path) fx_norm_names.add(_norm_plugin_name(e.get("name") or "")) + fx_norm_names.add(_norm_path_stem(e.get("path") or "")) elif e.get("is_unknown"): unknown_paths.add(path) + unknown_norm_names.add(_norm_plugin_name(e.get("name") or "")) + unknown_norm_names.add(_norm_path_stem(e.get("path") or "")) except Exception: pass blocked = fx_paths | unknown_paths @@ -229,6 +233,12 @@ async def list_plugins(current_user: dict = Depends(get_current_user)): # EQ.vst3...) nhưng path .dll ≠ path .vst3 → block theo path KHÔNG trúng. # Loại theo TÊN normalized (bỏ prefix iZ, lowercase alnum) — VST2 thật # (DSK Asian DreamZ, Kong Audio...) không trùng tên FX → vẫn giữ. + # Ngoài is_fx còn loại entry UNKNOWN theo TÊN: bridge timeout khi + # introspect VST3 (vd Ozone Pro.vst3, Tonal Balance Control Pro.vst3 — + # module treo 12s → skip) nên không vào fx_norm_names, nhưng VST2 legacy + # .dll CÙNG TÊN (Ozone Pro.dll) vẫn lọt vào nút Synth → load FX như + # instrument → không ra tiếng. UNKNOWN = không xác định loại → cũng + # không hiện là instrument (cùng chính sách block theo path ở trên). name = v.get("name") or "" if name.startswith("iZ") and "izotope" in ((v.get("path") or "").lower()): # iZotope KHÔNG sản xuất VST instrument — mọi module .dll/VST2 của @@ -236,9 +246,12 @@ async def list_plugins(current_user: dict = Depends(get_current_user)): # VST2 legacy không introspect được → bridge không đánh is_fx → lọt # vào nút Synth (iZOzonePro, iZRXProMusicRebalance, iZTonalBalanceControlPro). return True - if not fx_norm_names: + if not fx_norm_names and not unknown_norm_names: return False - return _norm_plugin_name(name) in fx_norm_names + nm_name = _norm_plugin_name(name) + nm_stem = _norm_path_stem(v.get("path") or "") + return (nm_name in fx_norm_names or nm_stem in fx_norm_names + or nm_name in unknown_norm_names or nm_stem in unknown_norm_names) if blocked: avail["vst_instruments"] = [v for v in avail["vst_instruments"] @@ -272,6 +285,16 @@ def _norm_plugin_name(name: str) -> str: s = s[2:] return s +def _norm_path_stem(path: str) -> str: + """Chuẩn hóa TÊN FILE (không phần mở rộng) của path — dùng cho entry UNKNOWN + mà bridge chỉ report filename kèm đuôi ('Ozone Pro.vst3') vì timeout khi + introspect: stem 'Ozone Pro' khớp VST2 legacy 'Ozone Pro.dll' cùng tên.""" + base = os.path.basename((path or "").replace("\\", "/")) + s = "".join(ch for ch in os.path.splitext(base)[0].lower() if ch.isalnum()) + if s.startswith("iz") and len(s) > 2: + s = s[2:] + return s + def _scan_soundfonts_in_dirs(dirs: list) -> list: """Walk các thư mục (plugin_dirs user) → danh sách soundfont .sf2/.sf3