fix(masterfx): Wave Observer scope khong tu chay (toggle default TAT) + preset VST master giu sau save/load
This commit is contained in:
+44
-3
@@ -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
|
||||
<span className="text-[9px] bg-cyan-950 text-cyan-400 border border-cyan-800/60 px-1.5 py-0.2 rounded font-mono">Real-time Oscilloscope</span>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<button onClick={() => setWoEnabled(!woEnabled)}
|
||||
className={`px-2 py-0.5 rounded text-[10px] font-bold border ${woEnabled ? 'bg-cyan-700 border-cyan-500 text-white' : 'bg-slate-800 border-slate-700 text-slate-300 hover:bg-slate-700'}`}>
|
||||
{woEnabled ? 'Scope: BẬT' : 'Scope: TẮT'}
|
||||
</button>
|
||||
{['Scope', 'Settings', 'Help', 'About'].map(tab => (
|
||||
<button key={tab} className={`px-2 py-0.5 rounded text-[10px] font-bold ${tab === 'Scope' ? 'bg-cyan-950 text-cyan-300 border border-cyan-800/60' : 'text-slate-400 hover:text-slate-200'}`}>
|
||||
{tab}
|
||||
@@ -14654,6 +14690,11 @@ const addMasterVst = (path) => { const fx = (masterFxList || []).find(f => f.pat
|
||||
{/* Scope Canvas */}
|
||||
<div className="relative w-full h-32 bg-[#090d16] border border-slate-800/80 rounded-lg overflow-hidden mb-2">
|
||||
<canvas ref={woCanvasRef} className="w-full h-full block"></canvas>
|
||||
{!woEnabled && (
|
||||
<div className="absolute inset-0 flex items-center justify-center text-[10px] font-mono text-slate-600 select-none pointer-events-none">
|
||||
Scope đang tắt — bấm [Scope: BẬT] để chạy
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Controls bar */}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -51,7 +51,7 @@
|
||||
<script src="/static/js/services/promptTemplateManager.js?v=202607281039"></script>
|
||||
<script src="/static/js/services/undoRedoEngine.js?v=202607290941"></script>
|
||||
<script src="/static/js/services/chordTheory.js?v=202608211300"></script>
|
||||
<script src="/static/js/app.precompiled.js?v=202608241700" defer></script>
|
||||
<script src="/static/js/app.precompiled.js?v=202608241730" defer></script>
|
||||
<link rel="stylesheet" href="/static/css/styles.css?v=202607271016">
|
||||
<style>
|
||||
:root {
|
||||
|
||||
Reference in New Issue
Block a user