diff --git a/app/static/js/app.jsx b/app/static/js/app.jsx index b7b5c67..a4fc652 100644 --- a/app/static/js/app.jsx +++ b/app/static/js/app.jsx @@ -11822,6 +11822,12 @@ const serializeProjectToSchema = (projectId, name, bpmVal, tracksList, subTabsLi section_store: sectionStore, mastering_settings: masteringSettings ? { ...masteringSettings, + // FIX preset VST master mất sau save/load: GUI capture (_capturedPresetByPath) + // trước đây chỉ merge vào main_session.master.fx_chain, còn mastering_settings + // (nguồn ưu tiên lúc deserialize) giữ preset cũ/rỗng → load lại mất settings. + // Merge cả vstFxChain + chain (entry vst3) để 2 nơi lưu đồng nhất. + vstFxChain: (masteringSettings.vstFxChain || []).map(s => ({ ...s, preset_b64: _capturedPresetByPath[s.path] || s.preset_b64 || '' })), + chain: (masteringSettings.chain || []).map(m => m && m.type === 'vst3' ? { ...m, preset_b64: _capturedPresetByPath[m.path] || m.preset_b64 || '' } : m), gui_open_path: (_persistMasterGuiOpen && _persistMasterGuiOpen.path) ? _persistMasterGuiOpen.path : (masteringSettings && masteringSettings.gui_open_path) || null, gui_open_name: (_persistMasterGuiOpen && _persistMasterGuiOpen.name) ? _persistMasterGuiOpen.name : (masteringSettings && masteringSettings.gui_open_name) || null } : null @@ -11919,8 +11925,22 @@ const deserializeProjectFromSchema = (schemaObj) => { masteringSettings: (() => { const migrated = { ..._migratedMastering }; const _masterVstSources = []; - (migrated.vstFxChain || []).forEach(s => { if (s && s.path && !_masterVstSources.some(x => x.path === s.path)) _masterVstSources.push(s); }); - _masterFx.forEach(s => { if (s && s.path && !_masterVstSources.some(x => x.path === s.path)) _masterVstSources.push(s); }); + // Merge preset: ưu tiên vstFxChain (thứ tự), nhưng nếu preset rỗng mà + // main_session.master.fx_chain có preset (project cũ lưu trước fix) → lấy + // preset không rỗng đó (fix: settings VST master mất sau save/load). + const _mergeVstSource = (s) => { + if (!s || !s.path) return; + const ex = _masterVstSources.find(x => x.path === s.path); + if (ex) { + if (!ex.preset_b64 && s.preset_b64) ex.preset_b64 = s.preset_b64; + if (!ex.name && s.name) ex.name = s.name; + if (ex.bypass === undefined && s.bypass !== undefined) ex.bypass = s.bypass; + return; + } + _masterVstSources.push({ ...s }); + }; + (migrated.vstFxChain || []).forEach(_mergeVstSource); + _masterFx.forEach(_mergeVstSource); const _finalChain = [...(migrated.chain || [])]; _masterVstSources.forEach(s => { if (!_finalChain.some(m => m.type === 'vst3' && m.path === s.path)) { @@ -13542,6 +13562,9 @@ const addMasterVst = (path) => { const fx = (masterFxList || []).find(f => f.pat const [woMode, setWoMode] = React.useState('waveform'); const [woDuration, setWoDuration] = React.useState(2.0); const [woZoom, setWoZoom] = React.useState(0.0); + // Scope KHÔNG tự chạy khi mở modal (fix: Wave Observer "built-in" auto-load + // khi nhấn VST FX) — chỉ render khi user bật toggle, mặc định TẮT. + const [woEnabled, setWoEnabled] = React.useState(false); const woPausedRef = React.useRef(woPaused); woPausedRef.current = woPaused; @@ -13553,6 +13576,8 @@ const addMasterVst = (path) => { const fx = (masterFxList || []).find(f => f.pat woDurationRef.current = woDuration; const woZoomRef = React.useRef(woZoom); woZoomRef.current = woZoom; + const woEnabledRef = React.useRef(woEnabled); + woEnabledRef.current = woEnabled; const ozStateRef = React.useRef(ozState); ozStateRef.current = ozState; @@ -13817,7 +13842,14 @@ const addMasterVst = (path) => { const fx = (masterFxList || []).find(f => f.pat // Wave Observer Oscilloscope Rendering const woCanvas = woCanvasRef.current; - if (woCanvas) { + if (woCanvas && !woEnabledRef.current) { + // Scope tắt (mặc định) — không chạy tự động: xóa canvas + zero meters. + const woCtx = woCanvas.getContext('2d'); + woCtx.clearRect(0, 0, woCanvas.width, woCanvas.height); + if (woLeftMeterRef.current) woLeftMeterRef.current.style.width = '0%'; + if (woRightMeterRef.current) woRightMeterRef.current.style.width = '0%'; + } + if (woCanvas && woEnabledRef.current) { const w = woCanvas.width, h = woCanvas.height; const woCtx = woCanvas.getContext('2d'); woCtx.clearRect(0, 0, w, h); @@ -14643,6 +14675,10 @@ const addMasterVst = (path) => { const fx = (masterFxList || []).find(f => f.pat Real-time Oscilloscope
+ {['Scope', 'Settings', 'Help', 'About'].map(tab => (