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 rời PIANO ROLL tab đã play (Space):
// play piano roll → stopAllPlayback dừng main → quay lại MAIN/SECTION
// bị CÂM. Resume startTrackPlayback(offset + elapsed thật) — 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') {
// Rời PIANO ROLL tab KHÔNG play: main/section play ngầm vẫn chạy (âm
// tiếp tục tự nhiên — không cần resume) → clear resume point.
// ⚠️ KHÔNG clear khi prevTab = main/session (đang DI CHUYỂN VÀO piano
// roll — mainResumeRef vừa set bởi handleEditMidiInTab — clear nhầm ở
// đây làm resume chết → quay lại 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 rời PIANO ROLL tab: mở piano roll lúc main
// đang play → bấm Space (play piano roll) → stopAllPlayback dừng main →
// quay lại MAIN/SECTION → CÂM. Lưu {offset, audioTime} lúc mở tab → khi
// rời tab resume startTrackPlayback(offset + elapsed thật).
const mainResumeRef = useRef(null);
currentTimeRef.current = currentTime;
// ── Keyboard Shortcuts ──
@@ -16424,7 +16454,15 @@ const App = () => {
// mở PIANO ROLL tab KHÔNG được dừng âm (user: dblclick mở tab lúc main
// play → âm main phải tiếp tục). 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 điểm resume: nếu user bấm Space trong piano roll (play piano roll
// → stopAllPlayback dừng main) → khi quay lại MAIN/SECTION resume main
// từ đúng vị trí âm (offset + elapsed thật) — 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 (mới mở, đang edit): playhead của
// MAIN/SECTION KHÔNG được tiếp tục di chuyển (yêu cầu user) — KHÔNG
// setCurrentTime. Loop phải TIẾP TỤC (rAF) để khi quay lại tab playhead
// không nhảy vọt sai lệch. ⚠️ KHÔNG check projectEnd ở đây: projectEnd
// tính theo activeTab — piano roll tab (sub-tab) → projectEnd = 1s →
// updatedTime (elapsed thật) >= 1 → stopAllPlayback NGAY → CÂM + panic
// notes. Âm main đã schedule hết từ startTrackPlayback — tự hết đúng
// lúc; khi quay lại MAIN nhánh main tự stop tại projectEnd thật.
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