fix(plugin-dirs): remove het dir - rescan khong con VST trong thu muc mac dinh (authoritative user dirs, khong fallback default khi da luu rong; list_scan_all/_scan_plugins chi scan dir user khai)
This commit is contained in:
+15
-3
@@ -69,7 +69,19 @@ def _effective_dirs() -> dict:
|
|||||||
plugin_dirs = [d for d in (user.get("plugin_dirs") or []) if d]
|
plugin_dirs = [d for d in (user.get("plugin_dirs") or []) if d]
|
||||||
vst_dir = settings.VST_DIR
|
vst_dir = settings.VST_DIR
|
||||||
soundfont_dir = settings.SOUNDFONT_DIR
|
soundfont_dir = settings.SOUNDFONT_DIR
|
||||||
# Backward compat: file cũ lưu vst_dir/soundfont_dir riêng → gộp vào list.
|
# User ĐÃ lưu plugin_dirs (kể cả [] — xóa hết dir) → dùng ĐÚNG danh sách
|
||||||
|
# đó, KHÔNG fallback default: nếu fallback, remove hết dir rồi re-scan
|
||||||
|
# vẫn còn VST trong thư mục mặc định (vd C:\Program Files\Common Files\
|
||||||
|
# VST3 → iZotope Ozone Pro load fail 0x7E vẫn hiện trong MASTERING PANEL).
|
||||||
|
if "plugin_dirs" in user:
|
||||||
|
return {
|
||||||
|
"plugin_dirs": plugin_dirs,
|
||||||
|
"vst_dir": vst_dir,
|
||||||
|
"soundfont_dir": soundfont_dir,
|
||||||
|
"plugin_dirs_user_set": True,
|
||||||
|
}
|
||||||
|
# Chưa từng lưu → backward compat (file cũ lưu vst_dir/soundfont_dir
|
||||||
|
# riêng) → gộp vào list; không có gì → fallback default env.
|
||||||
if not plugin_dirs:
|
if not plugin_dirs:
|
||||||
if user.get("vst_dir"):
|
if user.get("vst_dir"):
|
||||||
plugin_dirs.append(user["vst_dir"])
|
plugin_dirs.append(user["vst_dir"])
|
||||||
@@ -81,7 +93,7 @@ def _effective_dirs() -> dict:
|
|||||||
"plugin_dirs": plugin_dirs,
|
"plugin_dirs": plugin_dirs,
|
||||||
"vst_dir": vst_dir,
|
"vst_dir": vst_dir,
|
||||||
"soundfont_dir": soundfont_dir,
|
"soundfont_dir": soundfont_dir,
|
||||||
"plugin_dirs_user_set": bool(user.get("plugin_dirs")),
|
"plugin_dirs_user_set": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
class DirsRequest(BaseModel):
|
class DirsRequest(BaseModel):
|
||||||
@@ -184,7 +196,7 @@ def get_scanner():
|
|||||||
@router.get("/available")
|
@router.get("/available")
|
||||||
async def list_plugins(current_user: dict = Depends(get_current_user)):
|
async def list_plugins(current_user: dict = Depends(get_current_user)):
|
||||||
d = _effective_dirs()
|
d = _effective_dirs()
|
||||||
pm = PluginManager(vst_dir=d["vst_dir"], sf_dir=d["soundfont_dir"], upload_sf_dir=UPLOAD_SF_DIR, extra_vst_dirs=d["plugin_dirs"])
|
pm = PluginManager(vst_dir=d["vst_dir"], sf_dir=d["soundfont_dir"], upload_sf_dir=UPLOAD_SF_DIR, extra_vst_dirs=d["plugin_dirs"], user_dirs_override=d.get("plugin_dirs_user_set", False))
|
||||||
avail = pm.list_available()
|
avail = pm.list_available()
|
||||||
# Modal chọn instrument (nút Synth TCP) chỉ hiện soundfont + VSTi — loại
|
# Modal chọn instrument (nút Synth TCP) chỉ hiện soundfont + VSTi — loại
|
||||||
# VST FX (Ozone/Sonible/...) khỏi vst_instruments theo is_fx của bridge scan.
|
# VST FX (Ozone/Sonible/...) khỏi vst_instruments theo is_fx của bridge scan.
|
||||||
|
|||||||
+38
-6
@@ -210,6 +210,26 @@ def _load_user_plugin_dirs() -> list:
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def _user_plugin_dirs_configured() -> bool:
|
||||||
|
"""User ĐÃ lưu plugin_dirs trong Plugin Manager (kể cả danh sách rỗng)?
|
||||||
|
|
||||||
|
Phân biệt "chưa cấu hình" (fallback thư mục mặc định VST_DIR) với "đã
|
||||||
|
xóa hết dir" (chỉ scan đúng dir user khai - rỗng thì không scan gì).
|
||||||
|
Nếu không phân biệt, remove hết dir rồi re-scan vẫn còn VST trong thư
|
||||||
|
mục mặc định (vd C:\\Program Files\\Common Files\\VST3, iZotope Ozone Pro
|
||||||
|
load fail 0x7E vẫn hiện trong MASTERING PANEL)."""
|
||||||
|
try:
|
||||||
|
from app.config import settings as _st
|
||||||
|
path = os.path.join(_st.STORAGE_DIR, "plugin_dirs.json")
|
||||||
|
if os.path.exists(path):
|
||||||
|
with open(path, "r", encoding="utf-8") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
return "plugin_dirs" in data
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_plugin_manager(vst_dir=None, sf_dir=None, upload_sf_dir=None) -> "PluginManager":
|
def get_plugin_manager(vst_dir=None, sf_dir=None, upload_sf_dir=None) -> "PluginManager":
|
||||||
"""Singleton: reuse PluginManager when args match, else create new.
|
"""Singleton: reuse PluginManager when args match, else create new.
|
||||||
Default dirs từ settings (env/.env/docker-compose hoặc user override).
|
Default dirs từ settings (env/.env/docker-compose hoặc user override).
|
||||||
@@ -220,12 +240,13 @@ def get_plugin_manager(vst_dir=None, sf_dir=None, upload_sf_dir=None) -> "Plugin
|
|||||||
sf_dir = sf_dir or _st.SOUNDFONT_DIR
|
sf_dir = sf_dir or _st.SOUNDFONT_DIR
|
||||||
upload_sf_dir = upload_sf_dir or _st.STORAGE_DIR + "/soundfonts"
|
upload_sf_dir = upload_sf_dir or _st.STORAGE_DIR + "/soundfonts"
|
||||||
extra = _load_user_plugin_dirs()
|
extra = _load_user_plugin_dirs()
|
||||||
|
user_override = _user_plugin_dirs_configured()
|
||||||
global _PLUGIN_MANAGER_INSTANCE, _PLUGIN_MANAGER_ARGS
|
global _PLUGIN_MANAGER_INSTANCE, _PLUGIN_MANAGER_ARGS
|
||||||
args = (vst_dir, sf_dir, upload_sf_dir, tuple(extra))
|
args = (vst_dir, sf_dir, upload_sf_dir, tuple(extra), user_override)
|
||||||
if _PLUGIN_MANAGER_INSTANCE is not None and _PLUGIN_MANAGER_ARGS == args:
|
if _PLUGIN_MANAGER_INSTANCE is not None and _PLUGIN_MANAGER_ARGS == args:
|
||||||
return _PLUGIN_MANAGER_INSTANCE
|
return _PLUGIN_MANAGER_INSTANCE
|
||||||
_PLUGIN_MANAGER_ARGS = args
|
_PLUGIN_MANAGER_ARGS = args
|
||||||
_PLUGIN_MANAGER_INSTANCE = PluginManager(vst_dir, sf_dir, upload_sf_dir, extra_vst_dirs=extra)
|
_PLUGIN_MANAGER_INSTANCE = PluginManager(vst_dir, sf_dir, upload_sf_dir, extra_vst_dirs=extra, user_dirs_override=user_override)
|
||||||
return _PLUGIN_MANAGER_INSTANCE
|
return _PLUGIN_MANAGER_INSTANCE
|
||||||
|
|
||||||
def load_soundfont_cached(path: str):
|
def load_soundfont_cached(path: str):
|
||||||
@@ -289,7 +310,7 @@ def _classify_fx_category(name, path=""):
|
|||||||
return "utility"
|
return "utility"
|
||||||
|
|
||||||
class PluginManager:
|
class PluginManager:
|
||||||
def __init__(self, vst_dir=None, sf_dir=None, upload_sf_dir=None, extra_vst_dirs=None):
|
def __init__(self, vst_dir=None, sf_dir=None, upload_sf_dir=None, extra_vst_dirs=None, user_dirs_override=False):
|
||||||
from app.config import settings as _st
|
from app.config import settings as _st
|
||||||
self.vst_dir = vst_dir or _st.VST_DIR
|
self.vst_dir = vst_dir or _st.VST_DIR
|
||||||
self.sf_dir = sf_dir or _st.SOUNDFONT_DIR
|
self.sf_dir = sf_dir or _st.SOUNDFONT_DIR
|
||||||
@@ -298,11 +319,23 @@ class PluginManager:
|
|||||||
# list_available() phải thấy VSTi user đã scan (bug: nút
|
# list_available() phải thấy VSTi user đã scan (bug: nút
|
||||||
# Synth chỉ quét vst_dir env mặc định /opt/daw_engine/vst3).
|
# Synth chỉ quét vst_dir env mặc định /opt/daw_engine/vst3).
|
||||||
self.extra_vst_dirs = [d for d in (extra_vst_dirs or []) if d]
|
self.extra_vst_dirs = [d for d in (extra_vst_dirs or []) if d]
|
||||||
|
# user_dirs_override=True: user ĐÃ lưu plugin_dirs (kể cả rỗng) →
|
||||||
|
# chỉ scan đúng dir user khai, KHÔNG thêm vst_dir mặc định. Nếu không,
|
||||||
|
# remove hết dir rồi re-scan vẫn còn VST trong thư mục mặc định
|
||||||
|
# (vd C:\Program Files\Common Files\VST3 → iZotope 0x7E vẫn hiện).
|
||||||
|
self.user_dirs_override = bool(user_dirs_override)
|
||||||
self._sf_scan_cache = None # cache for _scan_soundfonts()
|
self._sf_scan_cache = None # cache for _scan_soundfonts()
|
||||||
self._fx_scan_cache = None # cache for list_fx()
|
self._fx_scan_cache = None # cache for list_fx()
|
||||||
self._fx_scan_all = None # cache for list_scan_all()
|
self._fx_scan_all = None # cache for list_scan_all()
|
||||||
self._fx_scan_all_ts = 0.0 # timestamp cache (TTL — tránh kẹt [] vĩnh viễn)
|
self._fx_scan_all_ts = 0.0 # timestamp cache (TTL — tránh kẹt [] vĩnh viễn)
|
||||||
|
|
||||||
|
def _vst_scan_dirs(self) -> list:
|
||||||
|
"""Thư mục quét VST: user đã lưu plugin_dirs → chỉ đúng dir user khai
|
||||||
|
(rỗng = không scan gì); chưa cấu hình → vst_dir mặc định + dir user."""
|
||||||
|
if self.user_dirs_override:
|
||||||
|
return list(self.extra_vst_dirs)
|
||||||
|
return [self.vst_dir] + list(self.extra_vst_dirs)
|
||||||
|
|
||||||
FX_SCAN_TTL = 300.0 # giây: cache scan VST tự hết hạn → MASTERING PANEL
|
FX_SCAN_TTL = 300.0 # giây: cache scan VST tự hết hạn → MASTERING PANEL
|
||||||
# không bao giờ kẹt danh sách cũ/rỗng; refresh=true vẫn ép scan ngay.
|
# không bao giờ kẹt danh sách cũ/rỗng; refresh=true vẫn ép scan ngay.
|
||||||
|
|
||||||
@@ -315,7 +348,7 @@ class PluginManager:
|
|||||||
|
|
||||||
def _scan_plugins(self) -> dict:
|
def _scan_plugins(self) -> dict:
|
||||||
plugins = {}
|
plugins = {}
|
||||||
for scan_dir in [self.vst_dir] + self.extra_vst_dirs:
|
for scan_dir in self._vst_scan_dirs():
|
||||||
if not scan_dir or not os.path.isdir(scan_dir):
|
if not scan_dir or not os.path.isdir(scan_dir):
|
||||||
continue
|
continue
|
||||||
for root, dirs, files in os.walk(scan_dir):
|
for root, dirs, files in os.walk(scan_dir):
|
||||||
@@ -545,8 +578,7 @@ class PluginManager:
|
|||||||
exe = find_fx_bridge_exe()
|
exe = find_fx_bridge_exe()
|
||||||
entries = []
|
entries = []
|
||||||
if exe:
|
if exe:
|
||||||
dirs = [d for d in [self.vst_dir] + self.extra_vst_dirs
|
dirs = [d for d in self._vst_scan_dirs() if d and os.path.isdir(d)]
|
||||||
if d and os.path.isdir(d)]
|
|
||||||
for d in dirs:
|
for d in dirs:
|
||||||
try:
|
try:
|
||||||
r = subprocess.run([exe, "--scan", d], capture_output=True,
|
r = subprocess.run([exe, "--scan", d], capture_output=True,
|
||||||
|
|||||||
Reference in New Issue
Block a user