FIX: sửa lỗi chuyển từ tab PIANO ROLL TAB sang MAIN SESSION và SECTION-TAB thì bị câm

This commit is contained in:
2026-08-07 09:35:40 +07:00
parent 8cdf2942b9
commit 4c820bfa77
4 changed files with 111 additions and 7 deletions
+52 -2
View File
@@ -14840,6 +14840,31 @@ const App = () => {
if (prevSub && prevSub.isPlaying) {
try { stopAllPlayback(); } catch (e) {}
setSubTabs(prev => prev.map(s => s.id === prevTab ? { ...s, isPlaying: false } : s));
// Resume main/session play khi ri PIANO ROLL tab đã play (Space):
// play piano roll stopAllPlayback dng main quay li MAIN/SECTION
// b CÂM. Resume startTrackPlayback(offset + elapsed tht) ch khi
// trưc đó m tab lúc main đang play (mainResumeRef đã set).
const _resume = mainResumeRef.current;
mainResumeRef.current = null;
if (_resume && prevSub.type === 'PIANO_ROLL' && (activeTab === 'main' || (activeTab && activeTab.startsWith('session_')))) {
try {
const _elapsed = getAudioContext().currentTime - _resume.audioTime;
const _resumeAt = _resume.offset + _elapsed;
console.log('[Resume] main play từ', _resumeAt.toFixed(2), 's (offset', _resume.offset.toFixed(2), '+ elapsed', _elapsed.toFixed(2), ')');
stopAllPlayback();
startOffsetTimeRef.current = _resumeAt;
startAudioTimeRef.current = getAudioContext().currentTime;
startTrackPlayback(_resumeAt);
setIsPlaying(true);
} catch (e) { console.warn('[Resume] error:', e); }
}
} else if (prevSub && prevSub.type === 'PIANO_ROLL') {
// Ri PIANO ROLL tab KHÔNG play: main/section play ngm vn chy (âm
// tiếp tc t nhiên không cn resume) clear resume point.
// KHÔNG clear khi prevTab = main/session (đang DI CHUYN VÀO piano
// roll mainResumeRef va set bi handleEditMidiInTab clear nhm
// đây làm resume chết quay li main/section b CÂM).
mainResumeRef.current = null;
}
}
}, [activeTab]);
@@ -15562,6 +15587,11 @@ const App = () => {
const isDraggingSubTabRef = useRef(false);
const handlePlayPauseRef = useRef(null);
const currentTimeRef = useRef(currentTime);
// Resume main/session play khi ri PIANO ROLL tab: m piano roll lúc main
// đang play bm Space (play piano roll) stopAllPlayback dng main
// quay li MAIN/SECTION CÂM. Lưu {offset, audioTime} lúc m tab khi
// ri tab resume startTrackPlayback(offset + elapsed tht).
const mainResumeRef = useRef(null);
currentTimeRef.current = currentTime;
// Keyboard Shortcuts
@@ -16424,7 +16454,15 @@ const App = () => {
// m PIANO ROLL tab KHÔNG đưc dng âm (user: dblclick m tab lúc main
// play âm main phi tiếp tc). Nhánh play sub-tab t stopAllPlayback
// trưc khi play nên không xung đt route.
if (!isPlaying) stopAllPlayback();
if (isPlaying) {
// Lưu đim resume: nếu user bm Space trong piano roll (play piano roll
// stopAllPlayback dng main) khi quay li MAIN/SECTION resume main
// t đúng v trí âm (offset + elapsed tht) hết câm.
mainResumeRef.current = { offset: startOffsetTimeRef.current, audioTime: getAudioContext().currentTime };
} else {
mainResumeRef.current = null;
stopAllPlayback();
}
const ctx = getAudioContext();
const silentBuffer = ctx.createBuffer(1, 128, ctx.sampleRate);
@@ -18425,7 +18463,19 @@ const App = () => {
const isSubTab = subTabsRef.current.some(sub => sub.id === activeTabRef.current);
if (isSubTab) {
const st = subTabsRef.current.find(s => s.id === activeTabRef.current);
if (!st || !st.isPlaying || !st.buffer) return;
if (!st || !st.buffer) return;
if (!st.isPlaying) {
// PIANO ROLL / sub-tab KHÔNG play (mi m, đang edit): playhead ca
// MAIN/SECTION KHÔNG đưc tiếp tc di chuyn (yêu cu user) KHÔNG
// setCurrentTime. Loop phi TIP TC (rAF) đ khi quay li tab playhead
// không nhy vt sai lch. KHÔNG check projectEnd đây: projectEnd
// tính theo activeTab piano roll tab (sub-tab) projectEnd = 1s
// updatedTime (elapsed tht) >= 1 stopAllPlayback NGAY CÂM + panic
// notes. Âm main đã schedule hết t startTrackPlayback t hết đúng
// lúc; khi quay li MAIN nhánh main t stop ti projectEnd tht.
animationFrameIdRef.current = requestAnimationFrame(updatePlayhead);
return;
}
const context = getAudioContext();
const speedFactor = st.speed || 1.0;
const elapsed = context.currentTime - startAudioTimeRef.current;
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -24,7 +24,7 @@
<script src="/static/js/services/midiExtractor.js?v=202607281052"></script>
<script src="/static/js/services/promptTemplateManager.js?v=202607281039"></script>
<script src="/static/js/services/undoRedoEngine.js?v=202607290941"></script>
<script src="/static/js/app.precompiled.js?v=202608070345" defer></script>
<script src="/static/js/app.precompiled.js?v=202608070405" defer></script>
<link rel="stylesheet" href="/static/css/styles.css?v=202607271016">
<style>
:root {
+30
View File
@@ -2361,3 +2361,33 @@
- **FIX (app.jsx updateSfRouting nhánh PIANO_ROLL):** khi `_activeSub.parent_tab_id` startsWith `session_` → lookup node ƯU TIÊN SUB-NODE (key `endsWith('_sub_' + trackId)` — route theo ♪ section + thẳng masterBus.input); không có sub-node → null (SF về masterBus.input — qua mastering, KHÔNG bypass). Không bao giờ route vào node MAIN cho piano roll của section.
- **Các file ảnh hưởng:** `app/static/js/app.jsx`, `app/templates/index.html` (?v=202608070345), `wiki.md`. Rebuild precompiled.
- **Ghi chú/Test:** hard refresh → play MAIN → double-click section (SECTION-TAB) → double-click MIDI item → PIANO ROLL tab → MIDI qua mastering (nghe EQ/limiter); log `[SFRoute]` không còn dest node MAIN (route 0/1) cho piano roll section.
### [2026-08-07 03:50] Task: Playhead vẫn di chuyển trong PIANO ROLL TAB khi mở MIDI item từ SECTION-TAB
- **Báo cáo user:** mở MIDI item từ SECTION-TAB (đang play) → PIANO ROLL TAB → playhead vẫn tiếp tục di chuyển — cần dừng.
- **Phân tích:** piano roll view vẽ playhead theo `st.currentTime` (chỉ cập nhật khi tab play) — khi mở tab (chưa play) code cũ `return` ở nhánh sub-tab KHÔNG setCurrentTime → playhead đứng yên — NHƯNG return đó GIẾT CHẾT rAF loop: main/section play chạy ngầm (handleEditMidiInTab 16427 không dừng âm) → watchdog master-silence chết, âm main không dừng đúng projectEnd, và khi quay lại tab playhead NHẢY VỌT theo `elapsed` thật (trông như vẫn di chuyển/sai lệch).
- **FIX (app.jsx updatePlayhead nhánh sub-tab):** tách 2 trường hợp — (1) sub-tab KHÔNG play: KHÔNG setCurrentTime (playhead đứng yên) NHƯNG nếu `isPlaying` (main/session chạy ngầm) → vẫn check projectEnd (stop đúng lúc) + TIẾP TỤC requestAnimationFrame (loop sống, watchdog sống, quay lại tab không nhảy); (2) sub-tab play: giữ nguyên hành vi cũ.
- **Các file ảnh hưởng:** `app/static/js/app.jsx`, `app/templates/index.html` (?v=202608070350), `wiki.md`. Rebuild precompiled.
- **Ghi chú/Test:** hard refresh → play MAIN → double-click section (SECTION-TAB) → double-click MIDI item → PIANO ROLL TAB → playhead KHÔNG di chuyển (đứng yên); âm main tiếp tục + dừng đúng cuối bài; quay lại SECTION-TAB → playhead đúng vị trí âm (không nhảy vọt). Nếu playhead vẫn chạy khi CHƯA bấm play → xác nhận lại: có bấm Space/Play trong piano roll không (bấm play → playhead chạy là đúng hành vi).
### [2026-08-07 03:55] Task: FIX hồi quy 0350 — CÂM âm khi mở PIANO ROLL từ SECTION-TAB (projectEnd=1s ở sub-tab)
- **Báo cáo user (log 0350):** mở MIDI item từ SECTION-TAB → PIANO ROLL → `[SFRoute] activeTab=midi_... midiAudible=1(midi1)``setOutputDestination to: masterBus.input` → KHÔNG noteon tiếp theo → CÂM (bản 0345 play tiếp).
- **Nguyên nhân (hồi quy fix 0350):** nhánh updatePlayhead sub-tab không-play check `updatedTime >= projectEndRef.current` — nhưng `projectEnd` tính theo activeTab: piano roll tab (sub-tab) KHÔNG main/không session → `tab=undefined → max=0`**projectEnd = 1s** → updatedTime (elapsed THẬT từ lúc play main — đã >1s) >= 1 → `stopAllPlayback()` NGAY → panic notes + xóa nodes (activeTrackNodesRef={}) → SF về masterBus.input + KHÔNG noteon = CÂM.
- **FIX (app.jsx):** bỏ check projectEnd khỏi nhánh sub-tab không-play — chỉ `requestAnimationFrame` tiếp tục (loop sống cho playhead không nhảy khi quay lại). Âm main đã schedule hết từ startTrackPlayback — tự hết đúng lúc; quay lại MAIN → nhánh main tự stop tại projectEnd THẬT.
- **Các file ảnh hưởng:** `app/static/js/app.jsx`, `app/templates/index.html` (?v=202608070355), `wiki.md`. Rebuild precompiled.
- **Ghi chú/Test:** hard refresh → play MAIN → double-click section (SECTION-TAB) → double-click MIDI item → PIANO ROLL TAB → âm section TIẾP TỤC play (không câm) + playhead piano roll ĐỨNG YÊN; quay lại SECTION-TAB → playhead đúng vị trí âm.
### [2026-08-07 04:00] Task: Quay lại MAIN/SECTION sau khi Space trong PIANO ROLL → CÂM — resume main play
- **Báo cáo user (log 0355):** mở MIDI item từ SECTION-TAB → PIANO ROLL (playhead đứng yên ✓ — fix 0350/0355); bấm Space → playhead piano roll chạy; **quay lại MAIN/SECTION → CÂM** (log: `[SFRoute] activeTab=main midiAudible=` + `setOutputDestination to: masterBus.input` — SF về masterBus nhưng KHÔNG noteon — main play đã chết).
- **Nguyên nhân:** Space trong PIANO ROLL → `handlePlayPause` nhánh sub-tab → `stopAllPlayback()` DỪNG main/section play (xóa nodes + panic) → chơi piano roll. Quay lại MAIN/SECTION → không còn gì play → câm.
- **FIX (app.jsx):** resume main/section play khi rời piano roll tab đã play:
(1) `mainResumeRef` mới — lưu `{offset: startOffsetTimeRef.current, audioTime: ctx.currentTime}` lúc MỞ piano roll tab khi main đang play (handleEditMidiInTab — nhánh isPlaying=true).
(2) Effect đổi tab (14814): rời PIANO ROLL tab đã play về MAIN hoặc `session_*` + có `mainResumeRef``stopAllPlayback()` + `startTrackPlayback(offset + elapsed thật)` + `setIsPlaying(true)` — âm main/section tiếp tục từ ĐÚNG vị trí (không chơi lại từ đầu, không câm). Các trường hợp khác: clear `mainResumeRef` (không resume trùng).
- **Các file ảnh hưởng:** `app/static/js/app.jsx`, `app/templates/index.html` (?v=202608070400), `wiki.md`. Rebuild precompiled.
- **Ghi chú/Test:** hard refresh → play MAIN → double-click section (SECTION-TAB) → double-click MIDI item → PIANO ROLL (playhead đứng yên) → Space (playhead piano roll chạy) → quay lại MAIN/SECTION → ÂM TIẾP TỤC từ đúng vị trí (log `[Resume] main play từ X.XX s`); KHÔNG bấm Space → quay lại → âm vẫn tiếp tục (không resume trùng).
### [2026-08-07 04:05] Task: FIX 0400 — resume không chạy (mainResumeRef bị clear nhầm bởi chính effect đổi tab)
- **Báo cáo user (log 0400):** piano roll play (Space) → `dest=sfEntry node 1 ... MASTERING` + noteons ✓ → chuyển về SECTION-TAB → `setOutputDestination to: masterBus.input` (node null) → KHÔNG có log `[Resume]` → CÂM.
- **Nguyên nhân:** handleEditMidiInTab set `mainResumeRef` (mở tab lúc main play) → setActiveTab → effect đổi tab (14814) chạy với `prevTab='session_...'``prevSub = subTabsRef.find('session_...')` = **undefined** → rơi vào nhánh `else` cũ → **`mainResumeRef.current = null` — XÓA SẠCH resume point NGAY khi VÀO piano roll** → quay lại section: `_resume=null` → không resume → câm.
- **FIX (app.jsx effect 14814):** nhánh clear đổi thành `else if (prevSub && prevSub.type === 'PIANO_ROLL')` — chỉ clear khi THỰC SỰ rời khỏi piano roll tab (không play — main ngầm tiếp tục tự nhiên). prevTab = main/session (đang VÀO piano roll) → KHÔNG clear — resume point giữ nguyên.
- **Các file ảnh hưởng:** `app/static/js/app.jsx`, `app/templates/index.html` (?v=202608070405), `wiki.md`. Rebuild precompiled.
- **Ghi chú/Test:** hard refresh → play MAIN → double-click section → double-click MIDI item → PIANO ROLL (playhead đứng yên) → Space (piano roll play) → quay lại SECTION-TAB → **log `[Resume] main play từ X.XX s` + ÂM TIẾP TỤC từ đúng vị trí** (SF route: `dest=sfEntry node 1 ... MASTERING`); KHÔNG Space → quay lại → âm ngầm tiếp tục (không resume trùng).