From d3a3adca8ab33dbde172e1a9083091f3cb625869 Mon Sep 17 00:00:00 2001 From: 3dtours Date: Sun, 26 Jul 2026 11:28:47 +0700 Subject: [PATCH] fix: realtime velocity with updatedNotes + ruler restart without onStop --- app/static/js/app.jsx | 77 +++++++++++++++++++------------- app/static/js/app.precompiled.js | 6 +-- 2 files changed, 49 insertions(+), 34 deletions(-) diff --git a/app/static/js/app.jsx b/app/static/js/app.jsx index 8223889..d70a0f0 100644 --- a/app/static/js/app.jsx +++ b/app/static/js/app.jsx @@ -5424,12 +5424,13 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, onClose, onUpdateNot const currentNote = notes[cursorNoteIdx]; const currentVal = ccMode === 'pan' ? ((currentNote.pan || 0) / 2.0 + 0.5) : (currentNote.velocity !== undefined ? currentNote.velocity : 0.8); if (Math.abs(currentVal - val) > 0.001) { - setNotes(prev => prev.map((n, i) => { + const updatedNotes = notes.map((n, i) => { if (i !== cursorNoteIdx) return n; if (ccMode === 'pan') return { ...n, pan: (val - 0.5) * 2.0 }; return { ...n, velocity: val }; - })); - if (isPlaying && onRescheduleMidi) onRescheduleMidi(); + }); + setNotes(updatedNotes); + if (isPlaying && onRescheduleMidi) onRescheduleMidi(updatedNotes); } ccDragRef.current = { active: true, lastBeat: beat, selectedMode: true, lastPainted: [cursorNoteIdx] }; } else { @@ -5444,11 +5445,13 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, onClose, onUpdateNot if (noteIdx !== -1) { const currentVal = ccMode === 'pan' ? ((notes[noteIdx].pan || 0) / 2.0 + 0.5) : (notes[noteIdx].velocity !== undefined ? notes[noteIdx].velocity : 0.8); if (Math.abs(currentVal - val) > 0.001) { - setNotes(prev => prev.map((n, i) => { + const updatedNotes = notes.map((n, i) => { if (i !== noteIdx) return n; if (ccMode === 'pan') return { ...n, pan: (val - 0.5) * 2.0 }; return { ...n, velocity: val }; - })); + }); + setNotes(updatedNotes); + if (isPlaying && onRescheduleMidi) onRescheduleMidi(updatedNotes); } } }; @@ -5474,12 +5477,13 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, onClose, onUpdateNot if (cursorNote && selectedNoteIds.includes(cursorNote.id) && !painted.includes(cursorNoteIdx)) { const currentVal = ccMode === 'pan' ? ((cursorNote.pan || 0) / 2.0 + 0.5) : (cursorNote.velocity !== undefined ? cursorNote.velocity : 0.8); if (Math.abs(currentVal - val) > 0.001) { - setNotes(prev => prev.map((n, i) => { + const updatedNotes = notes.map((n, i) => { if (i !== cursorNoteIdx) return n; if (ccMode === 'pan') return { ...n, pan: (val - 0.5) * 2.0 }; return { ...n, velocity: val }; - })); - if (isPlaying && onRescheduleMidi) onRescheduleMidi(); + }); + setNotes(updatedNotes); + if (isPlaying && onRescheduleMidi) onRescheduleMidi(updatedNotes); } drag.lastPainted = [...painted, cursorNoteIdx]; } @@ -5491,12 +5495,13 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, onClose, onUpdateNot if (candidateIdx !== -1 && !painted.includes(candidateIdx)) { const currentVal = ccMode === 'pan' ? ((notes[candidateIdx].pan || 0) / 2.0 + 0.5) : (notes[candidateIdx].velocity !== undefined ? notes[candidateIdx].velocity : 0.8); if (Math.abs(currentVal - val) > 0.001) { - setNotes(prev => prev.map((n, i) => { + const updatedNotes = notes.map((n, i) => { if (i !== candidateIdx) return n; if (ccMode === 'pan') return { ...n, pan: (val - 0.5) * 2.0 }; return { ...n, velocity: val }; - })); - if (isPlaying && onRescheduleMidi) onRescheduleMidi(); + }); + setNotes(updatedNotes); + if (isPlaying && onRescheduleMidi) onRescheduleMidi(updatedNotes); } drag.lastPainted = [...painted, candidateIdx]; } @@ -5855,11 +5860,21 @@ const beatSec = 60.0 / (parseInt(bpm) || 120); if (clickTime >= 0) { setSubTabs(prev => prev.map(s => s.id === st.id ? { ...s, currentTime: clickTime } : s)); if (isPlaying) { - onStop(); + setSubTabs(prev => prev.map(s => s.id === st.id ? { ...s, currentTime: clickTime } : s)); setTimeout(() => { - setSubTabs(prev => prev.map(s => s.id === st.id ? { ...s, currentTime: clickTime } : s)); - onPlayPause(); - }, 30); + stopAllPlayback(); + const sub = subTabs.find(s2 => s2.id === st.id); + if (sub) { + const ctx = getAudioContext(); + startOffsetTimeRef.current = clickTime; + startAudioTimeRef.current = ctx.currentTime; + startBufferOffsetRef.current = clickTime * (sub.speed || 1.0); + schedulePianoRollMidi(sub, clickTime); + startSubTabPlayback(sub, clickTime); + setSubTabs(prev => prev.map(s => s.id === st.id ? { ...s, currentTime: clickTime, isPlaying: true } : s)); + animationFrameIdRef.current = requestAnimationFrame(updatePlayhead); + } + }, 20); } } if (e.ctrlKey || e.metaKey) { @@ -10027,10 +10042,10 @@ const App = () => { }); } }; - const schedulePianoRollMidi = (st, offsetSeconds) => { + const schedulePianoRollMidi = (st, offsetSeconds, notesOverride) => { if (st.type !== 'PIANO_ROLL') return; const context = getAudioContext(); - const midiNotes = st.notes || []; + const midiNotes = notesOverride || st.notes || []; const bpmVal = parseInt(bpm) || 120; const secondsPerBeat = 60.0 / bpmVal; const startWallTime = context.currentTime; @@ -15814,20 +15829,20 @@ const App = () => { onMidiInputSelect: handleMidiInputSelect, activeMidiPitches: activeMidiPitches, onInstrumentSelect: (trackId) => { openInstrumentSelector(trackId); }, - onRescheduleMidi: () => { - const playingSub = subTabs.find(s => s.id === activeTab && s.type === 'PIANO_ROLL' && s.isPlaying); - if (playingSub) { - const offset = playingSub.currentTime || 0; - window.SonicSF.stopAll(); - setTimeout(() => { - const ctx = getAudioContext(); - startOffsetTimeRef.current = offset; - startAudioTimeRef.current = ctx.currentTime; - startBufferOffsetRef.current = offset * (playingSub.speed || 1.0); - schedulePianoRollMidi(playingSub, offset); - }, 20); - } - } + onRescheduleMidi: (updatedNotes) => { + const playingSub = subTabs.find(s => s.id === activeTab && s.type === 'PIANO_ROLL' && s.isPlaying); + if (playingSub) { + const offset = playingSub.currentTime || 0; + window.SonicSF.stopAll(); + setTimeout(() => { + const ctx = getAudioContext(); + startOffsetTimeRef.current = offset; + startAudioTimeRef.current = ctx.currentTime; + startBufferOffsetRef.current = offset * (playingSub.speed || 1.0); + schedulePianoRollMidi(playingSub, offset, updatedNotes); + }, 20); + } + } }); } const subTrack = tracks.find(t => t.id === st.trackId); diff --git a/app/static/js/app.precompiled.js b/app/static/js/app.precompiled.js index 5a37266..0eaba29 100644 --- a/app/static/js/app.precompiled.js +++ b/app/static/js/app.precompiled.js @@ -161,7 +161,7 @@ if(window.SonicSF){const ctx=getAudioContext();window.SonicSF.playNote(pitch,0.8 return n.start_beat<=maxBeat&¬eEnd>=minBeat;}else{// Right to left: select only if fully covered return n.start_beat>=minBeat&¬eEnd<=maxBeat;}}).map(n=>n.id);setSelectedNoteIds(insideIds);return;}// Right-click drag → erase sweep const rc=rightClickDragRef.current;if(rc.active&&(Math.abs(e.clientX-rc.startX)>5||Math.abs(e.clientY-rc.startY)>5)){rc.active=false;swallowContextMenuRef.current=true;notesBeforeDragRef.current=JSON.parse(JSON.stringify(notes));setDraggedNote({mode:'erase_sweep',visitedPitches:[]});return;}if(!draggedNote){let foundIdx=-1;for(let i=0;i=n.start_beat){foundIdx=i;break;}}}if(foundIdx!==-1){canvas.style.cursor='ew-resize';setHoveredResizeIdx(foundIdx);}else{canvas.style.cursor=activeRollTool==='eraser'?'pointer':'crosshair';setHoveredResizeIdx(-1);}return;}if(draggedNote.mode==='draw'){const snappedPitch=snapToScaleRef.current?snapPitchToScale(pitch,selectedScaleRef.current):pitch;const lastPitch=draggedNote.lastDrawnPitch!==undefined?draggedNote.lastDrawnPitch:draggedNote.startOffsetPitch;const pitchChanged=snappedPitch!==lastPitch;const noteBeats=draggedNote.noteStartBeats||[];const defaultDur=getSnapDuration(snapVal);if(pitchChanged){const brushIds=draggedNote.brushIds||[];if(brushIds.length>0&¬eBeats.length>0){const prevNoteId=brushIds[brushIds.length-1];const prevNoteBeat=noteBeats[noteBeats.length-1];const prevDur=Math.max(0.125,beat-prevNoteBeat);setNotes(prev=>prev.map(n=>{if(n.id!==prevNoteId)return n;return{...n,duration_beats:prevDur};}));}const newNote={id:'note_'+Date.now()+Math.random().toString(36).substr(2,8)+'_'+(noteBeats.length+1),pitch:snappedPitch,start_beat:beat,duration_beats:defaultDur,velocity:brushVelocityRef.current,pan:0.0};setNotes(prev=>[...prev,newNote]);setSelectedNoteIds(prev=>[...prev,newNote.id]);draggedNote.brushIds=[...brushIds,newNote.id];draggedNote.lastDrawnPitch=snappedPitch;draggedNote.noteStartBeats=[...noteBeats,beat];}else{const brushIds=draggedNote.brushIds||[];const lastBrushId=brushIds.length>0?brushIds[brushIds.length-1]:draggedNote.drawNoteId;const lastNoteBeat=noteBeats.length>0?noteBeats[noteBeats.length-1]:draggedNote.startOffsetBeat;if(lastBrushId){const extDur=Math.max(0.125,beat-lastNoteBeat);setNotes(prev=>prev.map(n=>{if(n.id!==lastBrushId)return n;return{...n,duration_beats:extDur};}));}}const container=gridScrollRef.current;if(container){const cr=container.getBoundingClientRect();const visTop=container.scrollTop;const visBot=visTop+container.clientHeight;const pitchPixel=(127-snappedPitch)*NoteHeight;const safeMargin=NoteHeight*2;if(pitchPixel{if(gridScrollRef.current)gridScrollRef.current.scrollTop=Math.max(0,gridScrollRef.current.scrollTop-Math.max(1,Math.floor(NoteHeight*0.5)));},16)};}}else if(pitchPixel+NoteHeight>visBot-safeMargin){const target=Math.min(container.scrollHeight-container.clientHeight,pitchPixel-container.clientHeight+safeMargin+NoteHeight);if(container.scrollTop!==target)container.scrollTop=target;if(!brushAutoScrollRef.current||brushAutoScrollRef.current.direction!=='down'){if(brushAutoScrollRef.current)clearInterval(brushAutoScrollRef.current.id);brushAutoScrollRef.current={direction:'down',id:setInterval(()=>{if(gridScrollRef.current)gridScrollRef.current.scrollTop=Math.min(gridScrollRef.current.scrollHeight-gridScrollRef.current.clientHeight,gridScrollRef.current.scrollTop+Math.max(1,Math.floor(NoteHeight*0.5)));},16)};}}else{if(brushAutoScrollRef.current){clearInterval(brushAutoScrollRef.current.id);brushAutoScrollRef.current=null;}}}return;}if(draggedNote.mode==='erase_sweep'){const erased=draggedNote.erasedIds||[];const target=notes.find(n=>n.pitch===pitch&&beat>=n.start_beat&&beatprev.filter(n=>n.id!==target.id));setSelectedNoteIds(prev=>prev.filter(id=>id!==target.id));}return;}if(draggedNote.mode==='scale'){const newEnd=getSnapBeat(Math.max(draggedNote.firstStart+0.125,beat),snapVal);const range=draggedNote.originalEnd-draggedNote.firstStart;if(range<=0)return;const scaleFactor=Math.max(0.01,(newEnd-draggedNote.firstStart)/range);const ids=draggedNote.selectedNoteIds||[];const firstStart=draggedNote.firstStart;const notesBefore=notesBeforeDragRef.current;if(!notesBefore)return;setNotes(prev=>prev.map(n=>{if(!ids.includes(n.id))return n;const orig=notesBefore?notesBefore.find(o=>o.id===n.id):null;const origStart=orig?orig.start_beat:n.start_beat;const origDur=orig?orig.duration_beats:n.duration_beats;const relStart=origStart-firstStart;const relEnd=relStart+origDur;return{...n,start_beat:firstStart+relStart*scaleFactor,duration_beats:Math.max(0.125,relEnd*scaleFactor-relStart*scaleFactor)};}));return;}if(draggedNote.mode==='resize'){const newDuration=getSnapBeat(Math.max(0.125,beat-draggedNote.originalStart),snapVal);setNotes(prev=>prev.map((n,idx)=>{if(idx!==draggedNote.idx)return n;return{...n,duration_beats:newDuration};}));}else if(draggedNote.mode==='move'){const firstOffset=draggedNote.selectedNotesOffset&&draggedNote.selectedNotesOffset[0];if(!firstOffset)return;const firstNote=notes.find(n=>n.id===firstOffset.id);if(!firstNote)return;const deltaBeat=getSnapBeat(beat-draggedNote.startOffsetBeat,snapVal)-firstOffset.originalStartBeat;// Clamp so no note goes past beat 0 -const minOrigStart=Math.min(...draggedNote.selectedNotesOffset.map(o=>o.originalStartBeat));const clampedDeltaBeat=minOrigStart+deltaBeat<0?-minOrigStart:deltaBeat;const deltaPitch=Math.round(pitch-draggedNote.startOffsetPitch);setNotes(prev=>prev.map(n=>{const offset=draggedNote.selectedNotesOffset.find(o=>o.id===n.id);if(!offset)return n;return{...n,start_beat:getSnapBeat(Math.max(0,offset.originalStartBeat+clampedDeltaBeat),snapVal),pitch:Math.max(0,Math.min(127,offset.originalPitch+deltaPitch))};}));}};const handleGridMouseUp=()=>{setDraggedNote(null);setSelectionMarquee(null);rightClickDragRef.current={active:false,startX:0,startY:0};if(brushAutoScrollRef.current){clearInterval(brushAutoScrollRef.current.id);brushAutoScrollRef.current=null;}};const handleContextMenu=e=>{e.preventDefault();if(swallowContextMenuRef.current){swallowContextMenuRef.current=false;return;}const pos={x:e.clientX,y:e.clientY,parentKey:null};scaleMenuOriginRef.current={x:pos.x,y:pos.y};setScaleMenuPos(pos);};const ccDragRef=React.useRef(null);const brushAutoScrollRef=React.useRef(null);const rightClickDragRef=React.useRef({active:false,startX:0,startY:0});const swallowContextMenuRef=React.useRef(false);const findCCNoteIndex=(b,mouseY,ccH)=>{const snapped=getSnapBeat(b,snapVal);const hits=[];notes.forEach((n,idx)=>{if(snapped>=n.start_beat&&snapped<=n.start_beat+n.duration_beats){const nv=ccMode==='pan'?(n.pan||0)*0.5+0.5:n.velocity!==undefined?n.velocity:0.8;const stemTop=ccH-(nv*(ccH-20)+10);hits.push({idx,dist:Math.abs(stemTop-mouseY)});}});if(hits.length>0){hits.sort((a,b)=>a.dist-b.dist);return hits[0].idx;}let nearest=-1;let minDist=Infinity;notes.forEach((n,idx)=>{const center=n.start_beat+n.duration_beats/2;const d=Math.abs(center-snapped);if(d{const canvas=ccCanvasRef.current;if(!canvas)return;const rect=canvas.getBoundingClientRect();const x=e.clientX-rect.left;const y=e.clientY-rect.top;const h=rect.height;const beat=x/pixelsPerBeat;const noteIdx=findCCNoteIndex(beat,y,h);const val=Math.max(0,Math.min(1,(h-y)/h));if(e.ctrlKey){if(selectedNoteIds.length>0){const cursorNoteIdx=findCCNoteIndex(beat,y,h);if(cursorNoteIdx!==-1&&selectedNoteIds.includes(notes[cursorNoteIdx]?notes[cursorNoteIdx].id:-1)){const currentNote=notes[cursorNoteIdx];const currentVal=ccMode==='pan'?(currentNote.pan||0)/2.0+0.5:currentNote.velocity!==undefined?currentNote.velocity:0.8;if(Math.abs(currentVal-val)>0.001){setNotes(prev=>prev.map((n,i)=>{if(i!==cursorNoteIdx)return n;if(ccMode==='pan')return{...n,pan:(val-0.5)*2.0};return{...n,velocity:val};}));if(isPlaying&&onRescheduleMidi)onRescheduleMidi();}ccDragRef.current={active:true,lastBeat:beat,selectedMode:true,lastPainted:[cursorNoteIdx]};}else{ccDragRef.current={active:true,lastBeat:beat,selectedMode:true,lastPainted:[]};}}else{ccDragRef.current={active:true,lastBeat:beat,lastPainted:noteIdx!==-1?[noteIdx]:[]};}return;}if(noteIdx!==-1){const currentVal=ccMode==='pan'?(notes[noteIdx].pan||0)/2.0+0.5:notes[noteIdx].velocity!==undefined?notes[noteIdx].velocity:0.8;if(Math.abs(currentVal-val)>0.001){setNotes(prev=>prev.map((n,i)=>{if(i!==noteIdx)return n;if(ccMode==='pan')return{...n,pan:(val-0.5)*2.0};return{...n,velocity:val};}));}}};const handleCCMouseMove=e=>{if(!ccDragRef.current||!ccDragRef.current.active)return;const canvas=ccCanvasRef.current;if(!canvas)return;const rect=canvas.getBoundingClientRect();const x=e.clientX-rect.left;const y=e.clientY-rect.top;const h=rect.height;const beat=x/pixelsPerBeat;const val=Math.max(0,Math.min(1,(h-y)/h));const drag=ccDragRef.current;const painted=drag.lastPainted||[];if(drag.selectedMode&&selectedNoteIds.length>0){const cursorNoteIdx=findCCNoteIndex(beat,y,h);if(cursorNoteIdx!==-1){const cursorNote=notes[cursorNoteIdx];if(cursorNote&&selectedNoteIds.includes(cursorNote.id)&&!painted.includes(cursorNoteIdx)){const currentVal=ccMode==='pan'?(cursorNote.pan||0)/2.0+0.5:cursorNote.velocity!==undefined?cursorNote.velocity:0.8;if(Math.abs(currentVal-val)>0.001){setNotes(prev=>prev.map((n,i)=>{if(i!==cursorNoteIdx)return n;if(ccMode==='pan')return{...n,pan:(val-0.5)*2.0};return{...n,velocity:val};}));if(isPlaying&&onRescheduleMidi)onRescheduleMidi();}drag.lastPainted=[...painted,cursorNoteIdx];}}return;}const candidateIdx=findCCNoteIndex(beat,y,h);if(candidateIdx!==-1&&!painted.includes(candidateIdx)){const currentVal=ccMode==='pan'?(notes[candidateIdx].pan||0)/2.0+0.5:notes[candidateIdx].velocity!==undefined?notes[candidateIdx].velocity:0.8;if(Math.abs(currentVal-val)>0.001){setNotes(prev=>prev.map((n,i)=>{if(i!==candidateIdx)return n;if(ccMode==='pan')return{...n,pan:(val-0.5)*2.0};return{...n,velocity:val};}));if(isPlaying&&onRescheduleMidi)onRescheduleMidi();}drag.lastPainted=[...painted,candidateIdx];}};const renderKeybed=()=>{const keys=[];for(let pitch=127;pitch>=PITCH_START;pitch--){const isBlack=[1,3,6,8,10].includes(pitch%12);const notesArray=['C','C#','D','D#','E','F','F#','G','G#','A','A#','B'];const octave=Math.floor(pitch/12)-1;const label=`${notesArray[pitch%12]}${octave}`;const showLabel=pitch%12===0;keys.push(/*#__PURE__*/React.createElement("div",{key:pitch,style:{height:`${NoteHeight}px`},className:`w-[60px] shrink-0 border-b border-zinc-800 text-[9px] font-bold flex items-center justify-end pr-2 transition cursor-pointer ${activeMidiPitches&&activeMidiPitches.has(pitch)?'bg-emerald-500 text-white border-emerald-400':isBlack?'bg-zinc-950 text-slate-500 border-zinc-900 hover:bg-zinc-800':'bg-white text-zinc-800 border-r border-zinc-400 hover:bg-amber-100'}`,onMouseDown:e=>{e.stopPropagation();keybedMouseDownRef.current=true;try{if(window.SonicSF){window.SonicSF.playNote(pitch,100,500,undefined,st.instrumentProgram,null);}}catch(err){console.error('playNote error:',err);}},onMouseEnter:e=>{if(keybedMouseDownRef.current){try{if(window.SonicSF){window.SonicSF.playNote(pitch,100,200,undefined,st.instrumentProgram,null);}}catch(err){console.error('playNote error:',err);}}},onMouseUp:()=>{keybedMouseDownRef.current=false;}},showLabel&&label));}return keys;};const handleScroll=e=>{if(keybedRef.current){keybedRef.current.scrollTop=e.currentTarget.scrollTop;}if(rulerScrollRef.current){rulerScrollRef.current.scrollLeft=e.currentTarget.scrollLeft;}if(ccWrapperRef.current){ccWrapperRef.current.scrollLeft=e.currentTarget.scrollLeft;}const el=e.currentTarget;const THRESHOLD=200;if(el.scrollLeft+el.clientWidth>=el.scrollWidth-THRESHOLD){const newBeats=rollBeatsRef.current+16;setRollBeats(newBeats);}};const handleKeybedScroll=e=>{if(gridScrollRef.current){gridScrollRef.current.scrollTop=e.currentTarget.scrollTop;}};const SCALES={"None":null,"Diatonic":{"Major":[0,2,4,5,7,9,11],"Minor":[0,2,3,5,7,8,10],"Dorian":[0,2,3,5,7,9,10],"Phrygian":[0,1,3,5,7,8,10],"Lydian":[0,2,4,6,7,9,11],"Mixolydian":[0,2,4,5,7,9,10],"Locrian":[0,1,3,5,6,8,10]},"Pentatonic":{"Major":[0,2,4,7,9],"Minor":[0,3,5,7,10],"Blues":[0,3,5,6,7,10],"Chinese":[0,2,4,7,9],"Vietnam":[0,2,6,7,10],"India":[0,2,5,7,9],"Japan":[0,2,5,7,9],"Africa":[0,3,5,7,10]},"Church":{"Dorian":[0,2,3,5,7,9,10],"Phrygian":[0,1,3,5,7,8,10],"Lydian":[0,2,4,6,7,9,11],"Mixolydian":[0,2,4,5,7,9,10]},"Jazz":{"Blues":[0,3,5,6,7,10],"Bebop":[0,2,4,5,7,9,10,11],"Diminished":[0,2,3,5,6,8,9,11]},"Asian Traditional":{"Chinese":[0,2,4,7,9],"Vietnam":[0,2,6,7,10],"Japan":[0,2,5,7,9],"India":[0,2,5,7,9],"Gamelan":[0,2,4,7,9],"Korea":[0,2,4,5,7,9]},"Middle Eastern":{"Hijaz":[0,1,4,5,7,8,11],"Nikriz":[0,1,4,5,7,8,10],"Rast":[0,2,4,5,7,8,10],"Saba":[0,1,3,4,7,8,10],"Bayati":[0,2,3,4,7,8,10]}};const[selectedScale,setSelectedScale]=React.useState(null);const selectedScaleRef=React.useRef(null);selectedScaleRef.current=selectedScale;const snapToScaleRef=React.useRef(true);snapToScaleRef.current=st.snapToScale!==undefined?st.snapToScale:true;const[scaleMenuPos,setScaleMenuPos]=React.useState(null);const scaleMenuOriginRef=React.useRef(null);const[showCC,setShowCC]=React.useState(true);const[ccHeight,setCcHeight]=React.useState(80);const snapPitchToScale=(pitch,scale)=>{if(!scale)return pitch;const octave=Math.floor(pitch/12);const noteInOctave=pitch%12;if(scale.includes(noteInOctave))return pitch;let best=noteInOctave;let minDist=12;scale.forEach(s=>{const dist=Math.abs(s-noteInOctave);if(dist{const closeMenu=()=>setScaleMenuPos(null);const origin=scaleMenuOriginRef.current||scaleMenuPos;const items=[];let subMenu=null;const isSameScale=(a,b)=>{if(!a||!b)return a===b;if(a.length!==b.length)return false;return a.every((v,i)=>v===b[i]);};const pushItem=(label,onClick,onHover)=>{const isActive=onClick._scale&&isSameScale(onClick._scale,selectedScale);items.push(React.createElement("div",{key:label,onClick:()=>{onClick();closeMenu();},onMouseEnter:onHover||undefined,className:"px-3 py-1.5 text-xs cursor-pointer hover:bg-amber-600 hover:text-white whitespace-nowrap "+(isActive?"bg-amber-800/40 text-amber-300":"text-zinc-300")},label));};Object.keys(SCALES).forEach(key=>{const val=SCALES[key];if(val===null){pushItem("None",()=>setSelectedScale(null));return;}if(Array.isArray(val)){pushItem(key,()=>setSelectedScale(val));}else{const parentKey=key;const isOpen=scaleMenuPos&&scaleMenuPos.parentKey===parentKey;pushItem(key+" ▸",()=>setSelectedScale(null),()=>{setScaleMenuPos({x:origin.x,y:origin.y,parentKey});});if(isOpen){const subItems=[];Object.keys(val).forEach(subKey=>{subItems.push(React.createElement("div",{key:subKey,onClick:()=>{setSelectedScale(val[subKey]);closeMenu();},className:"px-3 py-1.5 text-xs cursor-pointer hover:bg-amber-600 hover:text-white whitespace-nowrap "+(isSameScale(val[subKey],selectedScale)?"bg-amber-800/40 text-amber-300":"text-zinc-300")},subKey));});subMenu=React.createElement("div",{style:{position:"fixed",left:origin.x+150,top:origin.y,zIndex:10000},className:"bg-[#2a2a2a] border border-zinc-600 rounded shadow-xl py-1 min-w-[120px]"},...subItems);}}});return React.createElement(React.Fragment,null,React.createElement("div",{style:{position:"fixed",left:origin.x,top:origin.y,zIndex:9999},className:"bg-[#2a2a2a] border border-zinc-600 rounded shadow-xl py-1 min-w-[140px]"},...items),subMenu);};const renderBarLabels=()=>{const labels=[];const barsCount=Math.ceil(viewBeats/4);for(let bar=0;bar{e.stopPropagation();const barTime=bar*4*beatSec;setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,currentTime:barTime}:s));}},`Bar ${bar}`));}return labels;};const beatSec=60.0/(parseInt(bpm)||120);const playHeadX=(st.currentTime||0)/beatSec*pixelsPerBeat;return React.createElement("div",{className:"flex-1 flex overflow-hidden min-h-0 bg-[#1e1e1e] flex-col h-full"},/* 1. TOOLBAR HEADER */React.createElement("div",{className:"h-10 bg-[#282828] border-b border-zinc-900 flex items-center justify-between px-4 shrink-0 text-slate-200"},React.createElement("div",{className:"flex items-center gap-4"},React.createElement("span",{className:"text-xs font-bold text-yellow-500 uppercase flex items-center gap-1.5"},React.createElement("i",{"data-lucide":"music",className:"w-3.5 h-3.5"}),st.label),React.createElement("div",{className:"flex items-center gap-1 text-xs"},React.createElement("span",{className:"text-zinc-500 font-semibold"},"Snap to Scale"),React.createElement("button",{onClick:()=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,snapToScale:!(s.snapToScale!==undefined?s.snapToScale:true)}:s)),className:`w-7 h-4 rounded-full transition-colors relative ${(st.snapToScale!==undefined?st.snapToScale:true)?'bg-yellow-600':'bg-zinc-700'}`,style:{padding:0}},React.createElement("div",{className:`w-3 h-3 rounded-full bg-white absolute top-0.5 transition-transform ${(st.snapToScale!==undefined?st.snapToScale:true)?'translate-x-3.5':'translate-x-0.5'}`}))),React.createElement("div",{className:"flex items-center gap-1 text-xs"},React.createElement("span",{className:"text-zinc-500 font-semibold"},"Snap:"),React.createElement("select",{value:snapVal,onChange:e=>setSnapVal(e.target.value),className:"bg-zinc-800 border border-zinc-700 text-zinc-300 rounded px-1.5 py-0.5 outline-none focus:border-yellow-500"},['free','4','1','1/2','1/4','1/8','1/16','1/32'].map(v=>React.createElement("option",{key:v,value:v},v)))),React.createElement("button",{onClick:()=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,isArmed:!s.isArmed}:s)),className:`px-2 py-1 rounded text-xs font-bold ${st.isArmed?'bg-red-600 text-white':'bg-zinc-800 text-zinc-400'}`},"ARM"),React.createElement("select",{value:selectedMidiInputId||'',onChange:e=>onMidiInputSelect(e.target.value),className:"bg-zinc-800 border border-zinc-700 text-zinc-300 rounded px-1 py-0.5 text-xs outline-none max-w-[100px]"},React.createElement("option",{value:""},"Input"),React.createElement("option",{value:"ALL"},"Omni"),(midiDevices||[]).map(d=>React.createElement("option",{key:d.id,value:d.id},d.name||d.id))),React.createElement("button",{onClick:()=>onInstrumentSelect&&onInstrumentSelect(st.trackId),title:st.instrumentName||"Synth",className:`px-1.5 py-0.5 text-[10px] rounded font-mono font-bold border transition flex items-center gap-0.5 max-w-[50px] ${st.instrumentName?'bg-violet-900 text-violet-300 border-violet-700':'bg-zinc-800 text-zinc-500 border-transparent hover:text-zinc-300'}`},React.createElement("i",{"data-lucide":"music",className:"w-3 h-3 shrink-0"}),React.createElement("span",{className:"truncate text-[9px]"},st.instrumentName||'Synth')),React.createElement("div",{className:"flex items-center gap-1 ml-1 text-xs"},React.createElement("span",{className:"text-zinc-500"},"AI:"),React.createElement("input",{type:"number",value:aiBarStart,onChange:e=>setAiBarStart(parseInt(e.target.value)||0),className:"w-8 bg-zinc-900 border border-zinc-700 text-zinc-200 rounded px-1 py-0.5 text-xs text-center"}),React.createElement("span",{className:"text-zinc-500"},"-"),React.createElement("input",{type:"number",value:aiBarEnd,onChange:e=>setAiBarEnd(parseInt(e.target.value)||1),className:"w-8 bg-zinc-900 border border-zinc-700 text-zinc-200 rounded px-1 py-0.5 text-xs text-center"}),React.createElement("span",{className:"text-zinc-500"},"bar")),React.createElement("div",{className:"flex bg-zinc-800 p-0.5 rounded border border-zinc-700 text-xs"},['velocity','pan'].map(mode=>React.createElement("button",{key:mode,onClick:()=>setCcMode(mode),className:`px-2.5 py-1 rounded capitalize ${ccMode===mode?'bg-purple-900/60 text-purple-300 font-bold border border-purple-700':'text-zinc-400 hover:text-zinc-200'}`},mode)))),React.createElement("button",{onClick:()=>setShowCC(!showCC),className:`px-2 py-1 rounded text-xs ${showCC?'bg-purple-900/60 text-purple-300 border border-purple-700':'text-zinc-500 hover:text-zinc-300'}`},ccMode==='pan'?'Pan':'Vel'),React.createElement("div",{className:"flex items-center gap-1"},React.createElement("button",{onClick:()=>onSaveNotes(st.id,st.trackId,st.target_id,notes),className:"px-2.5 py-1 bg-emerald-600 hover:bg-emerald-500 text-white rounded text-xs flex items-center gap-1 transition font-semibold"},React.createElement("i",{"data-lucide":"save",className:"w-3 h-3"}),"Lưu"),React.createElement("button",{onClick:()=>{const ppq=480;const bpmNum=parseInt(bpm)||120;const ticksPerBeat=ppq;const events=[];(notes||[]).forEach(n=>{const startTick=Math.round((n.start_beat||0)*ticksPerBeat);const durTick=Math.round((n.duration_beats||1)*ticksPerBeat);const pitch=n.pitch||60;const vel=Math.round((n.velocity||0.8)*127);events.push({tick:startTick,type:'note_on',pitch,velocity:vel});events.push({tick:startTick+durTick,type:'note_off',pitch,velocity:0});});events.sort((a,b)=>a.tick-b.tick||(a.type==='note_off'?-1:1));const writeVLQ=(bytes,v)=>{let val=Math.max(0,v);const buf=[];buf.push(val&0x7F);while(val>0x7F){val>>=7;buf.push(0x80|val&0x7F);}for(let i=buf.length-1;i>=0;i--)bytes.push(buf[i]);};const trackBytes=[];let lastTick=0;events.forEach(ev=>{const delta=Math.max(0,ev.tick-lastTick);writeVLQ(trackBytes,delta);trackBytes.push(ev.type==='note_on'?0x90:0x80,ev.pitch,ev.velocity);lastTick=ev.tick;});writeVLQ(trackBytes,0);trackBytes.push(0xFF,0x2F,0x00);const trackData=[0x4D,0x54,0x72,0x6B];const len=trackBytes.length;trackData.push(len>>24&0xFF,len>>16&0xFF,len>>8&0xFF,len&0xFF);trackData.push(...trackBytes);const header=[0x4D,0x54,0x68,0x64,0x00,0x00,0x00,0x06,0x00,0x01,0x00,0x01,ppq>>8&0xFF,ppq&0xFF];const all=header.concat(trackData);const blob=new Blob([new Uint8Array(all)],{type:'audio/midi'});const url=URL.createObjectURL(blob);const a=document.createElement('a');a.href=url;a.download=(st.label||'midi')+'.mid';document.body.appendChild(a);a.click();document.body.removeChild(a);URL.revokeObjectURL(url);showToast('Đã xuất file MIDI!','success');},className:"px-2.5 py-1 bg-amber-700 hover:bg-amber-600 text-white rounded text-xs flex items-center gap-1 transition font-semibold"},React.createElement("i",{"data-lucide":"file-down",className:"w-3 h-3"}),"Export"),React.createElement("button",{onClick:onClose,className:"px-2.5 py-1 bg-zinc-800 hover:bg-zinc-700 text-zinc-300 border border-zinc-700 rounded text-xs flex items-center gap-1 transition"},React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"}),"Đóng"))),/* 2. BAR RULER (ĐÃ SỬA LẠI ĐÓNG NGOẶC ĐÚNG TẠI ĐÂY) */React.createElement("div",{className:"h-6 bg-[#1a1a1f] border-b border-zinc-900 flex shrink-0"},React.createElement("div",{className:"w-[60px] bg-[#222222] border-r border-zinc-900 shrink-0"}),React.createElement("div",{ref:rulerScrollRef,className:"flex-1 overflow-hidden",onMouseDown:e=>{const rect=e.currentTarget.getBoundingClientRect();const x=e.clientX-rect.left+e.currentTarget.scrollLeft;const clickBeat=x/pixelsPerBeat;const clickTime=clickBeat*beatSec;if(clickTime>=0){setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,currentTime:clickTime}:s));if(isPlaying){onStop();setTimeout(()=>{setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,currentTime:clickTime}:s));onPlayPause();},30);}}if(e.ctrlKey||e.metaKey){setLoopStartBeat(null);setLoopEndBeat(null);setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,selectionStart:null,selectionEnd:null}:s));return;}if(e.shiftKey){const beatSnap=getSnapBeat(clickBeat,snapVal);if(loopStartBeat===null){setLoopStartBeat(Math.max(0,beatSnap-4));setLoopEndBeat(Math.max(4,beatSnap));}else{setLoopEndBeat(Math.max(loopStartBeat+4,beatSnap));}return;}const snappedStartBeat=getSnapBeat(clickBeat,snapVal);const startData={startX:e.clientX,startBeat:snappedStartBeat,scrollLeft:e.currentTarget.scrollLeft};rulerDragRef.current=startData;const onMove=ev=>{const r=rulerScrollRef.current;if(!r||!rulerDragRef.current)return;const rRect=r.getBoundingClientRect();const bx=ev.clientX-rRect.left+rulerDragRef.current.scrollLeft;const rawBeat=Math.max(0,bx/pixelsPerBeat);const beat=getSnapBeat(rawBeat,snapVal);if(Math.abs(ev.clientX-rulerDragRef.current.startX)>5){const sBeat=Math.max(0,Math.min(rulerDragRef.current.startBeat,beat));const eBeat=Math.max(sBeat+1,Math.max(rulerDragRef.current.startBeat,beat));setLoopStartBeat(sBeat);setLoopEndBeat(eBeat);setIsLooping(true);setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,selectionStart:sBeat*beatSec,selectionEnd:eBeat*beatSec,isLooping:true}:s));}};const onUp=()=>{rulerDragRef.current=null;document.removeEventListener('mousemove',onMove);document.removeEventListener('mouseup',onUp);};document.addEventListener('mousemove',onMove);document.addEventListener('mouseup',onUp);}},React.createElement("div",{style:{width:`${viewWidth}px`,height:'100%'},className:"relative h-full font-mono text-[9px] text-zinc-500 font-bold"},renderBarLabels(),loopStartBeat!==null&&loopEndBeat!==null&&loopEndBeat>loopStartBeat&&React.createElement("div",{style:{left:`${loopStartBeat*pixelsPerBeat}px`,width:`${(loopEndBeat-loopStartBeat)*pixelsPerBeat}px`,top:0,bottom:0},className:"absolute bg-emerald-500/15 border-l border-r border-emerald-400"},React.createElement("div",{style:{position:'absolute',left:0,top:0,bottom:0,width:'4px',cursor:'ew-resize'},onMouseDown:e=>{e.stopPropagation();const startBeat=loopStartBeat;const onMove=ev=>{const r=rulerScrollRef.current;if(!r)return;const rRect=r.getBoundingClientRect();const bx=ev.clientX-rRect.left+r.scrollLeft;const nBeat=Math.max(0,Math.min(loopEndBeat-1,getSnapBeat(bx/pixelsPerBeat,snapVal)));setLoopStartBeat(nBeat);setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,selectionStart:nBeat*beatSec}:s));};const onUp=()=>{document.removeEventListener('mousemove',onMove);document.removeEventListener('mouseup',onUp);};document.addEventListener('mousemove',onMove);document.addEventListener('mouseup',onUp);}}),React.createElement("div",{style:{position:'absolute',right:0,top:0,bottom:0,width:'4px',cursor:'ew-resize'},onMouseDown:e=>{e.stopPropagation();const onMove=ev=>{const r=rulerScrollRef.current;if(!r)return;const rRect=r.getBoundingClientRect();const bx=ev.clientX-rRect.left+r.scrollLeft;const nBeat=Math.max(loopStartBeat+1,getSnapBeat(bx/pixelsPerBeat,snapVal));setLoopEndBeat(nBeat);setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,selectionEnd:nBeat*beatSec}:s));};const onUp=()=>{document.removeEventListener('mousemove',onMove);document.removeEventListener('mouseup',onUp);};document.addEventListener('mousemove',onMove);document.addEventListener('mouseup',onUp);}}),React.createElement("div",{style:{position:'absolute',left:'4px',right:'4px',top:0,bottom:0,cursor:'grab'},onMouseDown:e=>{e.stopPropagation();const startBeat=loopStartBeat;const range=loopEndBeat-loopStartBeat;const offsetBeat=startBeat+range/2;const onMove=ev=>{const r=rulerScrollRef.current;if(!r)return;const rRect=r.getBoundingClientRect();const bx=ev.clientX-rRect.left+r.scrollLeft;const centerBeat=getSnapBeat(bx/pixelsPerBeat,snapVal);const halfRange=range/2;const newStart=Math.max(0,centerBeat-halfRange);setLoopStartBeat(newStart);setLoopEndBeat(newStart+range);setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,selectionStart:newStart*beatSec,selectionEnd:(newStart+range)*beatSec}:s));};const onUp=()=>{document.removeEventListener('mousemove',onMove);document.removeEventListener('mouseup',onUp);};document.addEventListener('mousemove',onMove);document.addEventListener('mouseup',onUp);}}))))),/* 3. MAIN PIANO ROLL GRID (KEYBOARD + CANVAS) */React.createElement("div",{className:"flex-1 flex overflow-hidden min-h-0 relative"},React.createElement("div",{ref:keybedRef,onScroll:handleKeybedScroll,className:"w-[60px] overflow-y-auto flex flex-col border-r border-zinc-900 shrink-0",style:{scrollbarWidth:'none',msOverflowStyle:'none'}},renderKeybed()),React.createElement("div",{ref:gridScrollRef,onScroll:handleScroll,className:"flex-1 overflow-auto bg-[#141414] min-w-0"},React.createElement("div",{style:{width:`${viewWidth}px`,height:`${(128-PITCH_START)*NoteHeight}px`},className:"relative"},React.createElement("canvas",{ref:canvasRef,onMouseDown:handleGridMouseDown,onMouseMove:handleGridMouseMove,onMouseUp:handleGridMouseUp,onMouseLeave:handleGridMouseUp,onContextMenu:handleContextMenu,className:"absolute inset-0 cursor-crosshair"}),loopStartBeat!==null&&loopEndBeat!==null&&loopEndBeat>loopStartBeat&&React.createElement("div",{style:{left:`${loopStartBeat*pixelsPerBeat}px`,width:`${(loopEndBeat-loopStartBeat)*pixelsPerBeat}px`,top:0,bottom:0},className:"absolute bg-emerald-500/10 border-l border-r border-emerald-400/50 pointer-events-none"})))),/* 4. CC / VELOCITY LANE (ĐẶT Ở ĐÁY) */showCC&&React.createElement("div",{style:{height:`${ccHeight}px`},className:"bg-[#161616] border-t border-zinc-900 flex shrink-0 relative"},React.createElement("div",{onMouseDown:e=>{e.preventDefault();const startY=e.clientY;const startH=ccHeight;const onMove=ev=>{setCcHeight(Math.max(40,startH+startY-ev.clientY));};const onUp=()=>{document.removeEventListener('mousemove',onMove);document.removeEventListener('mouseup',onUp);};document.addEventListener('mousemove',onMove);document.addEventListener('mouseup',onUp);},className:"absolute top-0 left-0 right-0 h-1.5 cursor-n-resize z-10 hover:bg-purple-600/30"}),React.createElement("div",{className:"w-[60px] bg-[#222222] border-r border-zinc-900 flex items-center justify-center text-[10px] text-zinc-500 font-mono shrink-0 font-bold"},ccMode.toUpperCase()),React.createElement("div",{ref:ccWrapperRef,className:"flex-1 overflow-x-hidden min-w-0"},React.createElement("div",{style:{width:`${viewWidth}px`,height:'100%'},className:"relative"},React.createElement("canvas",{ref:ccCanvasRef,onMouseDown:handleCCMouseDown,onMouseMove:handleCCMouseMove,onMouseUp:()=>{if(ccDragRef.current)ccDragRef.current.selectedMode=false;ccDragRef.current=null;},onMouseLeave:()=>{if(ccDragRef.current)ccDragRef.current.selectedMode=false;ccDragRef.current=null;},className:"absolute inset-0"}),loopStartBeat!==null&&loopEndBeat!==null&&loopEndBeat>loopStartBeat&&React.createElement("div",{style:{left:`${loopStartBeat*pixelsPerBeat}px`,width:`${(loopEndBeat-loopStartBeat)*pixelsPerBeat}px`,top:0,bottom:0},className:"absolute bg-emerald-500/10 border-l border-r border-emerald-400/50 pointer-events-none"})))),/* 5. OVERLAY / CONTEXT MENU */scaleMenuPos&&renderScaleContextMenu());};const serializeTracksList=(tracksList,secondsPerBar)=>{return(tracksList||[]).map(t=>{let trackType="AUDIO";if(t.sections&&t.sections.length>0)trackType="SECTION";else if(t.midiItems&&t.midiItems.length>0)trackType="MIDI";const items=[];if(trackType==="AUDIO"&&t.clips){t.clips.forEach(c=>{const durationSec=c.buffer?c.buffer.duration:4.0;items.push({id:c.id,name:c.name||"Audio Clip",type:"AUDIO_ITEM",start_bar:c.startTime/secondsPerBar,duration_bars:durationSec/(c.speed||1.0)/secondsPerBar,clip_start_offset_bars:0.0,source_data:{audio_file_url:t.serverFileId?`/static/audio/uploads/${t.serverFileId}`:"",sample_rate:c.buffer?c.buffer.sampleRate:44100,channels:c.buffer?c.buffer.numberOfChannels:2,gain:1.0}});});}else if(trackType==="MIDI"&&t.midiItems){t.midiItems.forEach(m=>{items.push({id:m.id,name:m.name||"MIDI Item",type:"MIDI_ITEM",start_bar:m.startTime/secondsPerBar,duration_bars:m.duration?m.duration/secondsPerBar:4.0,clip_start_offset_bars:0.0,source_data:{total_buffer_bars:m.duration?m.duration/secondsPerBar:8.0,notes:(m.notes||[]).map(n=>({id:n.id||'note_'+Math.random().toString(36).substr(2,9),pitch:n.pitch||60,start_beat:n.start_beat||0.0,duration_beats:n.duration_beats||1.0,velocity:n.velocity||0.8,pan:n.pan||0.0}))}});});}else if(trackType==="SECTION"&&t.sections){t.sections.forEach(s=>{items.push({id:s.id,name:s.name||"Section Item",type:"SECTION_ITEM",start_bar:s.start/secondsPerBar,duration_bars:s.duration/secondsPerBar,clip_start_offset_bars:0.0,source_data:{referenced_section_id:s.sectionId||s.id}});});}return{id:t.id,name:t.name,type:trackType,volume_db:t.volumeDb||0.0,pan:t.pan||0.0,mute:t.muted||false,solo:t.solo||false,instrument_id:t.instrumentId||null,instrument_program:t.instrumentProgram!==undefined?t.instrumentProgram:null,instrument_name:t.instrumentName||null,items:items};});};const deserializeTracksList=(schemaTracks,secondsPerBar,sectionStore)=>{return(schemaTracks||[]).map(t=>{const clips=[];const sections=[];const midiItems=[];(t.items||[]).forEach(item=>{if(item.type==="AUDIO_ITEM"){const src=item.source_data||{};clips.push({id:item.id,name:item.name,startTime:item.start_bar*secondsPerBar,speed:1.0});}else if(item.type==="MIDI_ITEM"){const src=item.source_data||{};midiItems.push({id:item.id,name:item.name,startTime:item.start_bar*secondsPerBar,duration:item.duration_bars*secondsPerBar,notes:(src.notes||[]).map(n=>({id:n.id,pitch:n.pitch||60,start_beat:n.start_beat||0.0,duration_beats:n.duration_beats||1.0,velocity:n.velocity||0.8,pan:n.pan||0.0}))});}else if(item.type==="SECTION_ITEM"){const src=item.source_data||{};const secId=src.referenced_section_id;const secContainer=sectionStore?sectionStore[secId]:null;sections.push({id:item.id,name:item.name,start:item.start_bar*secondsPerBar,duration:item.duration_bars*secondsPerBar,sectionId:secId,tracks:secContainer?deserializeTracksList(secContainer.tracks,secondsPerBar,sectionStore):null});}});return{id:t.id,name:t.name,volumeDb:t.volume_db||0.0,pan:t.pan||0.0,muted:t.mute||false,solo:t.solo||false,color:t.id==='1'?'#0f766e':'#1d4ed8',markers:[],serverFileId:t.items&&t.items.find(i=>i.type==="AUDIO_ITEM")?.source_data?.audio_file_url?.split("/").pop()||null,clips:clips,sections:sections,midiItems:midiItems,instrumentId:t.instrument_id||null,instrumentProgram:t.instrument_program!==null?t.instrument_program:undefined,instrumentName:t.instrument_name||null};});};const serializeProjectToSchema=(projectId,name,bpmVal,tracksList,subTabsList,sessionTabsList)=>{const secondsPerBar=60.0/parseFloat(bpmVal||120)*4;const mainTracks=serializeTracksList(tracksList,secondsPerBar);const sectionStore={};// Helper: compute length_bars from tracks content +const minOrigStart=Math.min(...draggedNote.selectedNotesOffset.map(o=>o.originalStartBeat));const clampedDeltaBeat=minOrigStart+deltaBeat<0?-minOrigStart:deltaBeat;const deltaPitch=Math.round(pitch-draggedNote.startOffsetPitch);setNotes(prev=>prev.map(n=>{const offset=draggedNote.selectedNotesOffset.find(o=>o.id===n.id);if(!offset)return n;return{...n,start_beat:getSnapBeat(Math.max(0,offset.originalStartBeat+clampedDeltaBeat),snapVal),pitch:Math.max(0,Math.min(127,offset.originalPitch+deltaPitch))};}));}};const handleGridMouseUp=()=>{setDraggedNote(null);setSelectionMarquee(null);rightClickDragRef.current={active:false,startX:0,startY:0};if(brushAutoScrollRef.current){clearInterval(brushAutoScrollRef.current.id);brushAutoScrollRef.current=null;}};const handleContextMenu=e=>{e.preventDefault();if(swallowContextMenuRef.current){swallowContextMenuRef.current=false;return;}const pos={x:e.clientX,y:e.clientY,parentKey:null};scaleMenuOriginRef.current={x:pos.x,y:pos.y};setScaleMenuPos(pos);};const ccDragRef=React.useRef(null);const brushAutoScrollRef=React.useRef(null);const rightClickDragRef=React.useRef({active:false,startX:0,startY:0});const swallowContextMenuRef=React.useRef(false);const findCCNoteIndex=(b,mouseY,ccH)=>{const snapped=getSnapBeat(b,snapVal);const hits=[];notes.forEach((n,idx)=>{if(snapped>=n.start_beat&&snapped<=n.start_beat+n.duration_beats){const nv=ccMode==='pan'?(n.pan||0)*0.5+0.5:n.velocity!==undefined?n.velocity:0.8;const stemTop=ccH-(nv*(ccH-20)+10);hits.push({idx,dist:Math.abs(stemTop-mouseY)});}});if(hits.length>0){hits.sort((a,b)=>a.dist-b.dist);return hits[0].idx;}let nearest=-1;let minDist=Infinity;notes.forEach((n,idx)=>{const center=n.start_beat+n.duration_beats/2;const d=Math.abs(center-snapped);if(d{const canvas=ccCanvasRef.current;if(!canvas)return;const rect=canvas.getBoundingClientRect();const x=e.clientX-rect.left;const y=e.clientY-rect.top;const h=rect.height;const beat=x/pixelsPerBeat;const noteIdx=findCCNoteIndex(beat,y,h);const val=Math.max(0,Math.min(1,(h-y)/h));if(e.ctrlKey){if(selectedNoteIds.length>0){const cursorNoteIdx=findCCNoteIndex(beat,y,h);if(cursorNoteIdx!==-1&&selectedNoteIds.includes(notes[cursorNoteIdx]?notes[cursorNoteIdx].id:-1)){const currentNote=notes[cursorNoteIdx];const currentVal=ccMode==='pan'?(currentNote.pan||0)/2.0+0.5:currentNote.velocity!==undefined?currentNote.velocity:0.8;if(Math.abs(currentVal-val)>0.001){const updatedNotes=notes.map((n,i)=>{if(i!==cursorNoteIdx)return n;if(ccMode==='pan')return{...n,pan:(val-0.5)*2.0};return{...n,velocity:val};});setNotes(updatedNotes);if(isPlaying&&onRescheduleMidi)onRescheduleMidi(updatedNotes);}ccDragRef.current={active:true,lastBeat:beat,selectedMode:true,lastPainted:[cursorNoteIdx]};}else{ccDragRef.current={active:true,lastBeat:beat,selectedMode:true,lastPainted:[]};}}else{ccDragRef.current={active:true,lastBeat:beat,lastPainted:noteIdx!==-1?[noteIdx]:[]};}return;}if(noteIdx!==-1){const currentVal=ccMode==='pan'?(notes[noteIdx].pan||0)/2.0+0.5:notes[noteIdx].velocity!==undefined?notes[noteIdx].velocity:0.8;if(Math.abs(currentVal-val)>0.001){const updatedNotes=notes.map((n,i)=>{if(i!==noteIdx)return n;if(ccMode==='pan')return{...n,pan:(val-0.5)*2.0};return{...n,velocity:val};});setNotes(updatedNotes);if(isPlaying&&onRescheduleMidi)onRescheduleMidi(updatedNotes);}}};const handleCCMouseMove=e=>{if(!ccDragRef.current||!ccDragRef.current.active)return;const canvas=ccCanvasRef.current;if(!canvas)return;const rect=canvas.getBoundingClientRect();const x=e.clientX-rect.left;const y=e.clientY-rect.top;const h=rect.height;const beat=x/pixelsPerBeat;const val=Math.max(0,Math.min(1,(h-y)/h));const drag=ccDragRef.current;const painted=drag.lastPainted||[];if(drag.selectedMode&&selectedNoteIds.length>0){const cursorNoteIdx=findCCNoteIndex(beat,y,h);if(cursorNoteIdx!==-1){const cursorNote=notes[cursorNoteIdx];if(cursorNote&&selectedNoteIds.includes(cursorNote.id)&&!painted.includes(cursorNoteIdx)){const currentVal=ccMode==='pan'?(cursorNote.pan||0)/2.0+0.5:cursorNote.velocity!==undefined?cursorNote.velocity:0.8;if(Math.abs(currentVal-val)>0.001){const updatedNotes=notes.map((n,i)=>{if(i!==cursorNoteIdx)return n;if(ccMode==='pan')return{...n,pan:(val-0.5)*2.0};return{...n,velocity:val};});setNotes(updatedNotes);if(isPlaying&&onRescheduleMidi)onRescheduleMidi(updatedNotes);}drag.lastPainted=[...painted,cursorNoteIdx];}}return;}const candidateIdx=findCCNoteIndex(beat,y,h);if(candidateIdx!==-1&&!painted.includes(candidateIdx)){const currentVal=ccMode==='pan'?(notes[candidateIdx].pan||0)/2.0+0.5:notes[candidateIdx].velocity!==undefined?notes[candidateIdx].velocity:0.8;if(Math.abs(currentVal-val)>0.001){const updatedNotes=notes.map((n,i)=>{if(i!==candidateIdx)return n;if(ccMode==='pan')return{...n,pan:(val-0.5)*2.0};return{...n,velocity:val};});setNotes(updatedNotes);if(isPlaying&&onRescheduleMidi)onRescheduleMidi(updatedNotes);}drag.lastPainted=[...painted,candidateIdx];}};const renderKeybed=()=>{const keys=[];for(let pitch=127;pitch>=PITCH_START;pitch--){const isBlack=[1,3,6,8,10].includes(pitch%12);const notesArray=['C','C#','D','D#','E','F','F#','G','G#','A','A#','B'];const octave=Math.floor(pitch/12)-1;const label=`${notesArray[pitch%12]}${octave}`;const showLabel=pitch%12===0;keys.push(/*#__PURE__*/React.createElement("div",{key:pitch,style:{height:`${NoteHeight}px`},className:`w-[60px] shrink-0 border-b border-zinc-800 text-[9px] font-bold flex items-center justify-end pr-2 transition cursor-pointer ${activeMidiPitches&&activeMidiPitches.has(pitch)?'bg-emerald-500 text-white border-emerald-400':isBlack?'bg-zinc-950 text-slate-500 border-zinc-900 hover:bg-zinc-800':'bg-white text-zinc-800 border-r border-zinc-400 hover:bg-amber-100'}`,onMouseDown:e=>{e.stopPropagation();keybedMouseDownRef.current=true;try{if(window.SonicSF){window.SonicSF.playNote(pitch,100,500,undefined,st.instrumentProgram,null);}}catch(err){console.error('playNote error:',err);}},onMouseEnter:e=>{if(keybedMouseDownRef.current){try{if(window.SonicSF){window.SonicSF.playNote(pitch,100,200,undefined,st.instrumentProgram,null);}}catch(err){console.error('playNote error:',err);}}},onMouseUp:()=>{keybedMouseDownRef.current=false;}},showLabel&&label));}return keys;};const handleScroll=e=>{if(keybedRef.current){keybedRef.current.scrollTop=e.currentTarget.scrollTop;}if(rulerScrollRef.current){rulerScrollRef.current.scrollLeft=e.currentTarget.scrollLeft;}if(ccWrapperRef.current){ccWrapperRef.current.scrollLeft=e.currentTarget.scrollLeft;}const el=e.currentTarget;const THRESHOLD=200;if(el.scrollLeft+el.clientWidth>=el.scrollWidth-THRESHOLD){const newBeats=rollBeatsRef.current+16;setRollBeats(newBeats);}};const handleKeybedScroll=e=>{if(gridScrollRef.current){gridScrollRef.current.scrollTop=e.currentTarget.scrollTop;}};const SCALES={"None":null,"Diatonic":{"Major":[0,2,4,5,7,9,11],"Minor":[0,2,3,5,7,8,10],"Dorian":[0,2,3,5,7,9,10],"Phrygian":[0,1,3,5,7,8,10],"Lydian":[0,2,4,6,7,9,11],"Mixolydian":[0,2,4,5,7,9,10],"Locrian":[0,1,3,5,6,8,10]},"Pentatonic":{"Major":[0,2,4,7,9],"Minor":[0,3,5,7,10],"Blues":[0,3,5,6,7,10],"Chinese":[0,2,4,7,9],"Vietnam":[0,2,6,7,10],"India":[0,2,5,7,9],"Japan":[0,2,5,7,9],"Africa":[0,3,5,7,10]},"Church":{"Dorian":[0,2,3,5,7,9,10],"Phrygian":[0,1,3,5,7,8,10],"Lydian":[0,2,4,6,7,9,11],"Mixolydian":[0,2,4,5,7,9,10]},"Jazz":{"Blues":[0,3,5,6,7,10],"Bebop":[0,2,4,5,7,9,10,11],"Diminished":[0,2,3,5,6,8,9,11]},"Asian Traditional":{"Chinese":[0,2,4,7,9],"Vietnam":[0,2,6,7,10],"Japan":[0,2,5,7,9],"India":[0,2,5,7,9],"Gamelan":[0,2,4,7,9],"Korea":[0,2,4,5,7,9]},"Middle Eastern":{"Hijaz":[0,1,4,5,7,8,11],"Nikriz":[0,1,4,5,7,8,10],"Rast":[0,2,4,5,7,8,10],"Saba":[0,1,3,4,7,8,10],"Bayati":[0,2,3,4,7,8,10]}};const[selectedScale,setSelectedScale]=React.useState(null);const selectedScaleRef=React.useRef(null);selectedScaleRef.current=selectedScale;const snapToScaleRef=React.useRef(true);snapToScaleRef.current=st.snapToScale!==undefined?st.snapToScale:true;const[scaleMenuPos,setScaleMenuPos]=React.useState(null);const scaleMenuOriginRef=React.useRef(null);const[showCC,setShowCC]=React.useState(true);const[ccHeight,setCcHeight]=React.useState(80);const snapPitchToScale=(pitch,scale)=>{if(!scale)return pitch;const octave=Math.floor(pitch/12);const noteInOctave=pitch%12;if(scale.includes(noteInOctave))return pitch;let best=noteInOctave;let minDist=12;scale.forEach(s=>{const dist=Math.abs(s-noteInOctave);if(dist{const closeMenu=()=>setScaleMenuPos(null);const origin=scaleMenuOriginRef.current||scaleMenuPos;const items=[];let subMenu=null;const isSameScale=(a,b)=>{if(!a||!b)return a===b;if(a.length!==b.length)return false;return a.every((v,i)=>v===b[i]);};const pushItem=(label,onClick,onHover)=>{const isActive=onClick._scale&&isSameScale(onClick._scale,selectedScale);items.push(React.createElement("div",{key:label,onClick:()=>{onClick();closeMenu();},onMouseEnter:onHover||undefined,className:"px-3 py-1.5 text-xs cursor-pointer hover:bg-amber-600 hover:text-white whitespace-nowrap "+(isActive?"bg-amber-800/40 text-amber-300":"text-zinc-300")},label));};Object.keys(SCALES).forEach(key=>{const val=SCALES[key];if(val===null){pushItem("None",()=>setSelectedScale(null));return;}if(Array.isArray(val)){pushItem(key,()=>setSelectedScale(val));}else{const parentKey=key;const isOpen=scaleMenuPos&&scaleMenuPos.parentKey===parentKey;pushItem(key+" ▸",()=>setSelectedScale(null),()=>{setScaleMenuPos({x:origin.x,y:origin.y,parentKey});});if(isOpen){const subItems=[];Object.keys(val).forEach(subKey=>{subItems.push(React.createElement("div",{key:subKey,onClick:()=>{setSelectedScale(val[subKey]);closeMenu();},className:"px-3 py-1.5 text-xs cursor-pointer hover:bg-amber-600 hover:text-white whitespace-nowrap "+(isSameScale(val[subKey],selectedScale)?"bg-amber-800/40 text-amber-300":"text-zinc-300")},subKey));});subMenu=React.createElement("div",{style:{position:"fixed",left:origin.x+150,top:origin.y,zIndex:10000},className:"bg-[#2a2a2a] border border-zinc-600 rounded shadow-xl py-1 min-w-[120px]"},...subItems);}}});return React.createElement(React.Fragment,null,React.createElement("div",{style:{position:"fixed",left:origin.x,top:origin.y,zIndex:9999},className:"bg-[#2a2a2a] border border-zinc-600 rounded shadow-xl py-1 min-w-[140px]"},...items),subMenu);};const renderBarLabels=()=>{const labels=[];const barsCount=Math.ceil(viewBeats/4);for(let bar=0;bar{e.stopPropagation();const barTime=bar*4*beatSec;setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,currentTime:barTime}:s));}},`Bar ${bar}`));}return labels;};const beatSec=60.0/(parseInt(bpm)||120);const playHeadX=(st.currentTime||0)/beatSec*pixelsPerBeat;return React.createElement("div",{className:"flex-1 flex overflow-hidden min-h-0 bg-[#1e1e1e] flex-col h-full"},/* 1. TOOLBAR HEADER */React.createElement("div",{className:"h-10 bg-[#282828] border-b border-zinc-900 flex items-center justify-between px-4 shrink-0 text-slate-200"},React.createElement("div",{className:"flex items-center gap-4"},React.createElement("span",{className:"text-xs font-bold text-yellow-500 uppercase flex items-center gap-1.5"},React.createElement("i",{"data-lucide":"music",className:"w-3.5 h-3.5"}),st.label),React.createElement("div",{className:"flex items-center gap-1 text-xs"},React.createElement("span",{className:"text-zinc-500 font-semibold"},"Snap to Scale"),React.createElement("button",{onClick:()=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,snapToScale:!(s.snapToScale!==undefined?s.snapToScale:true)}:s)),className:`w-7 h-4 rounded-full transition-colors relative ${(st.snapToScale!==undefined?st.snapToScale:true)?'bg-yellow-600':'bg-zinc-700'}`,style:{padding:0}},React.createElement("div",{className:`w-3 h-3 rounded-full bg-white absolute top-0.5 transition-transform ${(st.snapToScale!==undefined?st.snapToScale:true)?'translate-x-3.5':'translate-x-0.5'}`}))),React.createElement("div",{className:"flex items-center gap-1 text-xs"},React.createElement("span",{className:"text-zinc-500 font-semibold"},"Snap:"),React.createElement("select",{value:snapVal,onChange:e=>setSnapVal(e.target.value),className:"bg-zinc-800 border border-zinc-700 text-zinc-300 rounded px-1.5 py-0.5 outline-none focus:border-yellow-500"},['free','4','1','1/2','1/4','1/8','1/16','1/32'].map(v=>React.createElement("option",{key:v,value:v},v)))),React.createElement("button",{onClick:()=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,isArmed:!s.isArmed}:s)),className:`px-2 py-1 rounded text-xs font-bold ${st.isArmed?'bg-red-600 text-white':'bg-zinc-800 text-zinc-400'}`},"ARM"),React.createElement("select",{value:selectedMidiInputId||'',onChange:e=>onMidiInputSelect(e.target.value),className:"bg-zinc-800 border border-zinc-700 text-zinc-300 rounded px-1 py-0.5 text-xs outline-none max-w-[100px]"},React.createElement("option",{value:""},"Input"),React.createElement("option",{value:"ALL"},"Omni"),(midiDevices||[]).map(d=>React.createElement("option",{key:d.id,value:d.id},d.name||d.id))),React.createElement("button",{onClick:()=>onInstrumentSelect&&onInstrumentSelect(st.trackId),title:st.instrumentName||"Synth",className:`px-1.5 py-0.5 text-[10px] rounded font-mono font-bold border transition flex items-center gap-0.5 max-w-[50px] ${st.instrumentName?'bg-violet-900 text-violet-300 border-violet-700':'bg-zinc-800 text-zinc-500 border-transparent hover:text-zinc-300'}`},React.createElement("i",{"data-lucide":"music",className:"w-3 h-3 shrink-0"}),React.createElement("span",{className:"truncate text-[9px]"},st.instrumentName||'Synth')),React.createElement("div",{className:"flex items-center gap-1 ml-1 text-xs"},React.createElement("span",{className:"text-zinc-500"},"AI:"),React.createElement("input",{type:"number",value:aiBarStart,onChange:e=>setAiBarStart(parseInt(e.target.value)||0),className:"w-8 bg-zinc-900 border border-zinc-700 text-zinc-200 rounded px-1 py-0.5 text-xs text-center"}),React.createElement("span",{className:"text-zinc-500"},"-"),React.createElement("input",{type:"number",value:aiBarEnd,onChange:e=>setAiBarEnd(parseInt(e.target.value)||1),className:"w-8 bg-zinc-900 border border-zinc-700 text-zinc-200 rounded px-1 py-0.5 text-xs text-center"}),React.createElement("span",{className:"text-zinc-500"},"bar")),React.createElement("div",{className:"flex bg-zinc-800 p-0.5 rounded border border-zinc-700 text-xs"},['velocity','pan'].map(mode=>React.createElement("button",{key:mode,onClick:()=>setCcMode(mode),className:`px-2.5 py-1 rounded capitalize ${ccMode===mode?'bg-purple-900/60 text-purple-300 font-bold border border-purple-700':'text-zinc-400 hover:text-zinc-200'}`},mode)))),React.createElement("button",{onClick:()=>setShowCC(!showCC),className:`px-2 py-1 rounded text-xs ${showCC?'bg-purple-900/60 text-purple-300 border border-purple-700':'text-zinc-500 hover:text-zinc-300'}`},ccMode==='pan'?'Pan':'Vel'),React.createElement("div",{className:"flex items-center gap-1"},React.createElement("button",{onClick:()=>onSaveNotes(st.id,st.trackId,st.target_id,notes),className:"px-2.5 py-1 bg-emerald-600 hover:bg-emerald-500 text-white rounded text-xs flex items-center gap-1 transition font-semibold"},React.createElement("i",{"data-lucide":"save",className:"w-3 h-3"}),"Lưu"),React.createElement("button",{onClick:()=>{const ppq=480;const bpmNum=parseInt(bpm)||120;const ticksPerBeat=ppq;const events=[];(notes||[]).forEach(n=>{const startTick=Math.round((n.start_beat||0)*ticksPerBeat);const durTick=Math.round((n.duration_beats||1)*ticksPerBeat);const pitch=n.pitch||60;const vel=Math.round((n.velocity||0.8)*127);events.push({tick:startTick,type:'note_on',pitch,velocity:vel});events.push({tick:startTick+durTick,type:'note_off',pitch,velocity:0});});events.sort((a,b)=>a.tick-b.tick||(a.type==='note_off'?-1:1));const writeVLQ=(bytes,v)=>{let val=Math.max(0,v);const buf=[];buf.push(val&0x7F);while(val>0x7F){val>>=7;buf.push(0x80|val&0x7F);}for(let i=buf.length-1;i>=0;i--)bytes.push(buf[i]);};const trackBytes=[];let lastTick=0;events.forEach(ev=>{const delta=Math.max(0,ev.tick-lastTick);writeVLQ(trackBytes,delta);trackBytes.push(ev.type==='note_on'?0x90:0x80,ev.pitch,ev.velocity);lastTick=ev.tick;});writeVLQ(trackBytes,0);trackBytes.push(0xFF,0x2F,0x00);const trackData=[0x4D,0x54,0x72,0x6B];const len=trackBytes.length;trackData.push(len>>24&0xFF,len>>16&0xFF,len>>8&0xFF,len&0xFF);trackData.push(...trackBytes);const header=[0x4D,0x54,0x68,0x64,0x00,0x00,0x00,0x06,0x00,0x01,0x00,0x01,ppq>>8&0xFF,ppq&0xFF];const all=header.concat(trackData);const blob=new Blob([new Uint8Array(all)],{type:'audio/midi'});const url=URL.createObjectURL(blob);const a=document.createElement('a');a.href=url;a.download=(st.label||'midi')+'.mid';document.body.appendChild(a);a.click();document.body.removeChild(a);URL.revokeObjectURL(url);showToast('Đã xuất file MIDI!','success');},className:"px-2.5 py-1 bg-amber-700 hover:bg-amber-600 text-white rounded text-xs flex items-center gap-1 transition font-semibold"},React.createElement("i",{"data-lucide":"file-down",className:"w-3 h-3"}),"Export"),React.createElement("button",{onClick:onClose,className:"px-2.5 py-1 bg-zinc-800 hover:bg-zinc-700 text-zinc-300 border border-zinc-700 rounded text-xs flex items-center gap-1 transition"},React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"}),"Đóng"))),/* 2. BAR RULER (ĐÃ SỬA LẠI ĐÓNG NGOẶC ĐÚNG TẠI ĐÂY) */React.createElement("div",{className:"h-6 bg-[#1a1a1f] border-b border-zinc-900 flex shrink-0"},React.createElement("div",{className:"w-[60px] bg-[#222222] border-r border-zinc-900 shrink-0"}),React.createElement("div",{ref:rulerScrollRef,className:"flex-1 overflow-hidden",onMouseDown:e=>{const rect=e.currentTarget.getBoundingClientRect();const x=e.clientX-rect.left+e.currentTarget.scrollLeft;const clickBeat=x/pixelsPerBeat;const clickTime=clickBeat*beatSec;if(clickTime>=0){setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,currentTime:clickTime}:s));if(isPlaying){setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,currentTime:clickTime}:s));setTimeout(()=>{stopAllPlayback();const sub=subTabs.find(s2=>s2.id===st.id);if(sub){const ctx=getAudioContext();startOffsetTimeRef.current=clickTime;startAudioTimeRef.current=ctx.currentTime;startBufferOffsetRef.current=clickTime*(sub.speed||1.0);schedulePianoRollMidi(sub,clickTime);startSubTabPlayback(sub,clickTime);setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,currentTime:clickTime,isPlaying:true}:s));animationFrameIdRef.current=requestAnimationFrame(updatePlayhead);}},20);}}if(e.ctrlKey||e.metaKey){setLoopStartBeat(null);setLoopEndBeat(null);setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,selectionStart:null,selectionEnd:null}:s));return;}if(e.shiftKey){const beatSnap=getSnapBeat(clickBeat,snapVal);if(loopStartBeat===null){setLoopStartBeat(Math.max(0,beatSnap-4));setLoopEndBeat(Math.max(4,beatSnap));}else{setLoopEndBeat(Math.max(loopStartBeat+4,beatSnap));}return;}const snappedStartBeat=getSnapBeat(clickBeat,snapVal);const startData={startX:e.clientX,startBeat:snappedStartBeat,scrollLeft:e.currentTarget.scrollLeft};rulerDragRef.current=startData;const onMove=ev=>{const r=rulerScrollRef.current;if(!r||!rulerDragRef.current)return;const rRect=r.getBoundingClientRect();const bx=ev.clientX-rRect.left+rulerDragRef.current.scrollLeft;const rawBeat=Math.max(0,bx/pixelsPerBeat);const beat=getSnapBeat(rawBeat,snapVal);if(Math.abs(ev.clientX-rulerDragRef.current.startX)>5){const sBeat=Math.max(0,Math.min(rulerDragRef.current.startBeat,beat));const eBeat=Math.max(sBeat+1,Math.max(rulerDragRef.current.startBeat,beat));setLoopStartBeat(sBeat);setLoopEndBeat(eBeat);setIsLooping(true);setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,selectionStart:sBeat*beatSec,selectionEnd:eBeat*beatSec,isLooping:true}:s));}};const onUp=()=>{rulerDragRef.current=null;document.removeEventListener('mousemove',onMove);document.removeEventListener('mouseup',onUp);};document.addEventListener('mousemove',onMove);document.addEventListener('mouseup',onUp);}},React.createElement("div",{style:{width:`${viewWidth}px`,height:'100%'},className:"relative h-full font-mono text-[9px] text-zinc-500 font-bold"},renderBarLabels(),loopStartBeat!==null&&loopEndBeat!==null&&loopEndBeat>loopStartBeat&&React.createElement("div",{style:{left:`${loopStartBeat*pixelsPerBeat}px`,width:`${(loopEndBeat-loopStartBeat)*pixelsPerBeat}px`,top:0,bottom:0},className:"absolute bg-emerald-500/15 border-l border-r border-emerald-400"},React.createElement("div",{style:{position:'absolute',left:0,top:0,bottom:0,width:'4px',cursor:'ew-resize'},onMouseDown:e=>{e.stopPropagation();const startBeat=loopStartBeat;const onMove=ev=>{const r=rulerScrollRef.current;if(!r)return;const rRect=r.getBoundingClientRect();const bx=ev.clientX-rRect.left+r.scrollLeft;const nBeat=Math.max(0,Math.min(loopEndBeat-1,getSnapBeat(bx/pixelsPerBeat,snapVal)));setLoopStartBeat(nBeat);setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,selectionStart:nBeat*beatSec}:s));};const onUp=()=>{document.removeEventListener('mousemove',onMove);document.removeEventListener('mouseup',onUp);};document.addEventListener('mousemove',onMove);document.addEventListener('mouseup',onUp);}}),React.createElement("div",{style:{position:'absolute',right:0,top:0,bottom:0,width:'4px',cursor:'ew-resize'},onMouseDown:e=>{e.stopPropagation();const onMove=ev=>{const r=rulerScrollRef.current;if(!r)return;const rRect=r.getBoundingClientRect();const bx=ev.clientX-rRect.left+r.scrollLeft;const nBeat=Math.max(loopStartBeat+1,getSnapBeat(bx/pixelsPerBeat,snapVal));setLoopEndBeat(nBeat);setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,selectionEnd:nBeat*beatSec}:s));};const onUp=()=>{document.removeEventListener('mousemove',onMove);document.removeEventListener('mouseup',onUp);};document.addEventListener('mousemove',onMove);document.addEventListener('mouseup',onUp);}}),React.createElement("div",{style:{position:'absolute',left:'4px',right:'4px',top:0,bottom:0,cursor:'grab'},onMouseDown:e=>{e.stopPropagation();const startBeat=loopStartBeat;const range=loopEndBeat-loopStartBeat;const offsetBeat=startBeat+range/2;const onMove=ev=>{const r=rulerScrollRef.current;if(!r)return;const rRect=r.getBoundingClientRect();const bx=ev.clientX-rRect.left+r.scrollLeft;const centerBeat=getSnapBeat(bx/pixelsPerBeat,snapVal);const halfRange=range/2;const newStart=Math.max(0,centerBeat-halfRange);setLoopStartBeat(newStart);setLoopEndBeat(newStart+range);setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,selectionStart:newStart*beatSec,selectionEnd:(newStart+range)*beatSec}:s));};const onUp=()=>{document.removeEventListener('mousemove',onMove);document.removeEventListener('mouseup',onUp);};document.addEventListener('mousemove',onMove);document.addEventListener('mouseup',onUp);}}))))),/* 3. MAIN PIANO ROLL GRID (KEYBOARD + CANVAS) */React.createElement("div",{className:"flex-1 flex overflow-hidden min-h-0 relative"},React.createElement("div",{ref:keybedRef,onScroll:handleKeybedScroll,className:"w-[60px] overflow-y-auto flex flex-col border-r border-zinc-900 shrink-0",style:{scrollbarWidth:'none',msOverflowStyle:'none'}},renderKeybed()),React.createElement("div",{ref:gridScrollRef,onScroll:handleScroll,className:"flex-1 overflow-auto bg-[#141414] min-w-0"},React.createElement("div",{style:{width:`${viewWidth}px`,height:`${(128-PITCH_START)*NoteHeight}px`},className:"relative"},React.createElement("canvas",{ref:canvasRef,onMouseDown:handleGridMouseDown,onMouseMove:handleGridMouseMove,onMouseUp:handleGridMouseUp,onMouseLeave:handleGridMouseUp,onContextMenu:handleContextMenu,className:"absolute inset-0 cursor-crosshair"}),loopStartBeat!==null&&loopEndBeat!==null&&loopEndBeat>loopStartBeat&&React.createElement("div",{style:{left:`${loopStartBeat*pixelsPerBeat}px`,width:`${(loopEndBeat-loopStartBeat)*pixelsPerBeat}px`,top:0,bottom:0},className:"absolute bg-emerald-500/10 border-l border-r border-emerald-400/50 pointer-events-none"})))),/* 4. CC / VELOCITY LANE (ĐẶT Ở ĐÁY) */showCC&&React.createElement("div",{style:{height:`${ccHeight}px`},className:"bg-[#161616] border-t border-zinc-900 flex shrink-0 relative"},React.createElement("div",{onMouseDown:e=>{e.preventDefault();const startY=e.clientY;const startH=ccHeight;const onMove=ev=>{setCcHeight(Math.max(40,startH+startY-ev.clientY));};const onUp=()=>{document.removeEventListener('mousemove',onMove);document.removeEventListener('mouseup',onUp);};document.addEventListener('mousemove',onMove);document.addEventListener('mouseup',onUp);},className:"absolute top-0 left-0 right-0 h-1.5 cursor-n-resize z-10 hover:bg-purple-600/30"}),React.createElement("div",{className:"w-[60px] bg-[#222222] border-r border-zinc-900 flex items-center justify-center text-[10px] text-zinc-500 font-mono shrink-0 font-bold"},ccMode.toUpperCase()),React.createElement("div",{ref:ccWrapperRef,className:"flex-1 overflow-x-hidden min-w-0"},React.createElement("div",{style:{width:`${viewWidth}px`,height:'100%'},className:"relative"},React.createElement("canvas",{ref:ccCanvasRef,onMouseDown:handleCCMouseDown,onMouseMove:handleCCMouseMove,onMouseUp:()=>{if(ccDragRef.current)ccDragRef.current.selectedMode=false;ccDragRef.current=null;},onMouseLeave:()=>{if(ccDragRef.current)ccDragRef.current.selectedMode=false;ccDragRef.current=null;},className:"absolute inset-0"}),loopStartBeat!==null&&loopEndBeat!==null&&loopEndBeat>loopStartBeat&&React.createElement("div",{style:{left:`${loopStartBeat*pixelsPerBeat}px`,width:`${(loopEndBeat-loopStartBeat)*pixelsPerBeat}px`,top:0,bottom:0},className:"absolute bg-emerald-500/10 border-l border-r border-emerald-400/50 pointer-events-none"})))),/* 5. OVERLAY / CONTEXT MENU */scaleMenuPos&&renderScaleContextMenu());};const serializeTracksList=(tracksList,secondsPerBar)=>{return(tracksList||[]).map(t=>{let trackType="AUDIO";if(t.sections&&t.sections.length>0)trackType="SECTION";else if(t.midiItems&&t.midiItems.length>0)trackType="MIDI";const items=[];if(trackType==="AUDIO"&&t.clips){t.clips.forEach(c=>{const durationSec=c.buffer?c.buffer.duration:4.0;items.push({id:c.id,name:c.name||"Audio Clip",type:"AUDIO_ITEM",start_bar:c.startTime/secondsPerBar,duration_bars:durationSec/(c.speed||1.0)/secondsPerBar,clip_start_offset_bars:0.0,source_data:{audio_file_url:t.serverFileId?`/static/audio/uploads/${t.serverFileId}`:"",sample_rate:c.buffer?c.buffer.sampleRate:44100,channels:c.buffer?c.buffer.numberOfChannels:2,gain:1.0}});});}else if(trackType==="MIDI"&&t.midiItems){t.midiItems.forEach(m=>{items.push({id:m.id,name:m.name||"MIDI Item",type:"MIDI_ITEM",start_bar:m.startTime/secondsPerBar,duration_bars:m.duration?m.duration/secondsPerBar:4.0,clip_start_offset_bars:0.0,source_data:{total_buffer_bars:m.duration?m.duration/secondsPerBar:8.0,notes:(m.notes||[]).map(n=>({id:n.id||'note_'+Math.random().toString(36).substr(2,9),pitch:n.pitch||60,start_beat:n.start_beat||0.0,duration_beats:n.duration_beats||1.0,velocity:n.velocity||0.8,pan:n.pan||0.0}))}});});}else if(trackType==="SECTION"&&t.sections){t.sections.forEach(s=>{items.push({id:s.id,name:s.name||"Section Item",type:"SECTION_ITEM",start_bar:s.start/secondsPerBar,duration_bars:s.duration/secondsPerBar,clip_start_offset_bars:0.0,source_data:{referenced_section_id:s.sectionId||s.id}});});}return{id:t.id,name:t.name,type:trackType,volume_db:t.volumeDb||0.0,pan:t.pan||0.0,mute:t.muted||false,solo:t.solo||false,instrument_id:t.instrumentId||null,instrument_program:t.instrumentProgram!==undefined?t.instrumentProgram:null,instrument_name:t.instrumentName||null,items:items};});};const deserializeTracksList=(schemaTracks,secondsPerBar,sectionStore)=>{return(schemaTracks||[]).map(t=>{const clips=[];const sections=[];const midiItems=[];(t.items||[]).forEach(item=>{if(item.type==="AUDIO_ITEM"){const src=item.source_data||{};clips.push({id:item.id,name:item.name,startTime:item.start_bar*secondsPerBar,speed:1.0});}else if(item.type==="MIDI_ITEM"){const src=item.source_data||{};midiItems.push({id:item.id,name:item.name,startTime:item.start_bar*secondsPerBar,duration:item.duration_bars*secondsPerBar,notes:(src.notes||[]).map(n=>({id:n.id,pitch:n.pitch||60,start_beat:n.start_beat||0.0,duration_beats:n.duration_beats||1.0,velocity:n.velocity||0.8,pan:n.pan||0.0}))});}else if(item.type==="SECTION_ITEM"){const src=item.source_data||{};const secId=src.referenced_section_id;const secContainer=sectionStore?sectionStore[secId]:null;sections.push({id:item.id,name:item.name,start:item.start_bar*secondsPerBar,duration:item.duration_bars*secondsPerBar,sectionId:secId,tracks:secContainer?deserializeTracksList(secContainer.tracks,secondsPerBar,sectionStore):null});}});return{id:t.id,name:t.name,volumeDb:t.volume_db||0.0,pan:t.pan||0.0,muted:t.mute||false,solo:t.solo||false,color:t.id==='1'?'#0f766e':'#1d4ed8',markers:[],serverFileId:t.items&&t.items.find(i=>i.type==="AUDIO_ITEM")?.source_data?.audio_file_url?.split("/").pop()||null,clips:clips,sections:sections,midiItems:midiItems,instrumentId:t.instrument_id||null,instrumentProgram:t.instrument_program!==null?t.instrument_program:undefined,instrumentName:t.instrument_name||null};});};const serializeProjectToSchema=(projectId,name,bpmVal,tracksList,subTabsList,sessionTabsList)=>{const secondsPerBar=60.0/parseFloat(bpmVal||120)*4;const mainTracks=serializeTracksList(tracksList,secondsPerBar);const sectionStore={};// Helper: compute length_bars from tracks content const computeLengthBars=(tracksArr,spb)=>{let maxSec=0;(tracksArr||[]).forEach(tr=>{(tr.clips||[]).forEach(c=>{const end=(c.startTime||0)+(c.buffer?c.buffer.duration/(c.speed||1.0):4);if(end>maxSec)maxSec=end;});(tr.midiItems||[]).forEach(m=>{const end=(m.startTime||0)+(m.duration||4);if(end>maxSec)maxSec=end;});});return Math.ceil((maxSec||4)/spb);};// 1. Populate from sessionTabsList (open tabs) (sessionTabsList||[]).forEach(st=>{const serializedTracks=serializeTracksList(st.tracks,secondsPerBar);sectionStore[st.sectionId]={id:st.sectionId,name:st.name,is_root:false,length_bars:computeLengthBars(st.tracks,secondsPerBar),auto_compute_length:true,tracks:serializedTracks,color:st.color||null};});// 2. Also populate from tracksList (closed tabs saved inside Section items) const scanForSections=tracks=>{(tracks||[]).forEach(t=>{if(t.sections){t.sections.forEach(s=>{const secId=s.sectionId||s.id;if(s.tracks&&!sectionStore[secId]){sectionStore[secId]={id:secId,name:s.name,is_root:false,length_bars:computeLengthBars(s.tracks,secondsPerBar),auto_compute_length:true,tracks:serializeTracksList(s.tracks,secondsPerBar),color:s.color||null};}if(s.tracks){scanForSections(s.tracks);}});}});};scanForSections(tracksList);const subTabs=(subTabsList||[]).map(st=>{return{id:st.id,label:st.label,type:st.type,track_id:st.trackId,target_id:st.target_id,parent_tab_id:st.parent_tab_id,notes:st.notes||[],duration:st.duration||4,instrument_program:st.instrumentProgram,instrument_name:st.instrumentName,current_time:st.currentTime||0,color:st.color||null};});return{project_id:projectId||'proj_'+Date.now(),metadata:{title:name||"Dự án mới",bpm:parseFloat(bpmVal||120),time_signature_numerator:4,time_signature_denominator:4,sample_rate:44100},main_session:{id:"main",name:"MAIN SESSION",is_root:true,length_bars:(()=>{let maxBar=16.0;(mainTracks||[]).forEach(t=>{(t.items||[]).forEach(item=>{const end=(item.start_bar||0)+(item.duration_bars||4);if(end>maxBar)maxBar=end;});});return maxBar;})(),auto_compute_length:true,tracks:mainTracks},sub_tabs:subTabs,section_store:sectionStore};};const deserializeProjectFromSchema=schemaObj=>{const bpmVal=schemaObj.metadata?schemaObj.metadata.bpm:120;const secondsPerBar=60.0/bpmVal*4;const sectionStore=schemaObj.section_store||{};const restoredTracks=deserializeTracksList(schemaObj.main_session.tracks,secondsPerBar,sectionStore);const restoredSessionTabs=[];Object.keys(sectionStore).forEach(secId=>{const secContainer=sectionStore[secId];const secTracks=deserializeTracksList(secContainer.tracks,secondsPerBar,sectionStore);restoredSessionTabs.push({id:'session_'+secId,name:secContainer.name,sectionId:secId,tracks:secTracks,length_bars:secContainer.length_bars||16.0,auto_compute_length:secContainer.auto_compute_length!==undefined?secContainer.auto_compute_length:true,color:secContainer.color||null});});const restoredSubTabs=(schemaObj.sub_tabs||[]).map(st=>{return{id:st.id,label:st.label,type:st.type,trackId:st.track_id,target_id:st.target_id,parent_tab_id:st.parent_tab_id,notes:st.notes||[],duration:st.duration||4,instrumentProgram:st.instrument_program,instrumentName:st.instrument_name,currentTime:st.current_time||0,color:st.color||null};});return{bpm:bpmVal,tracks:restoredTracks,sessionTabs:restoredSessionTabs,subTabs:restoredSubTabs};};const App=()=>{// ── State Definitions ── @@ -286,7 +286,7 @@ const subMidiItems=subTrack.midiItems||[];if(window.SonicSF&&subMidiItems.length if(noteStartMain>=secStart&¬eStartMain{const context=getAudioContext();const track=tracks.find(t=>t.id===trackId);if(!track)return;const clips=track.clips&&track.clips.length>0?track.clips:track.buffer?[{id:'default',buffer:track.buffer,startTime:track.startTime||0,name:track.name,speed:track.speed||1.0}]:[];// Get or create persistent gain & panner for real-time control const gainNode=getOrCreateTrackNode(track,context);const pannerNode=activeTrackNodesRef.current[track.id].pannerNode;clips.forEach(clip=>{if(!clip.buffer)return;const source=context.createBufferSource();source.buffer=clip.buffer;source.playbackRate.value=clip.speed||1.0;source.connect(gainNode);gainNode.connect(pannerNode);const clipStart=clip.startTime||0;const clipDuration=clip.buffer.duration/(clip.speed||1.0);const clipEnd=clipStart+clipDuration;if(offsetTime0)&&window.SonicSF){const bpmVal=parseInt(bpm)||120;const secondsPerBeat=60.0/bpmVal;midiItems.forEach(item=>{const notes=item.notes||[];notes.forEach(note=>{const noteStartSec=item.startTime+(note.start_beat||0)*secondsPerBeat;const noteDurSec=(note.duration_beats||1)*secondsPerBeat;const noteEndSec=noteStartSec+noteDurSec;if(offsetTime{if(st.type!=='PIANO_ROLL')return;const context=getAudioContext();const midiNotes=st.notes||[];const bpmVal=parseInt(bpm)||120;const secondsPerBeat=60.0/bpmVal;const startWallTime=context.currentTime;const track=activeTracksRef.current?activeTracksRef.current.find(t=>t.id===st.trackId):null;const destNode=getOrCreateTrackNode(track,context);const instrumentProgram=track?track.instrumentProgram:undefined;midiNotes.forEach(note=>{const noteOnBeat=note.start_beat||0;const noteDurBeat=note.duration_beats||1;const noteStartSec=noteOnBeat*secondsPerBeat;const noteDurSec=noteDurBeat*secondsPerBeat;if(noteStartSec+noteDurSec>offsetSeconds){const effectiveStart=Math.max(0,noteStartSec-offsetSeconds);const effectiveDur=noteDurSec-Math.max(0,offsetSeconds-noteStartSec);const scheduledTime=startWallTime+effectiveStart;const durMs=effectiveDur*1000;if(window.SonicSF){window.SonicSF.playNote(note.pitch||60,note.velocity||0.8,durMs,scheduledTime,instrumentProgram,destNode);}}});};const handlePlayPause=()=>{if(activeTab!=='main'&&!activeTab.startsWith('session_')){// Sub-tab playback transport +const midiItems=track.midiItems||[];if((track.type==='MIDI'||midiItems.length>0)&&window.SonicSF){const bpmVal=parseInt(bpm)||120;const secondsPerBeat=60.0/bpmVal;midiItems.forEach(item=>{const notes=item.notes||[];notes.forEach(note=>{const noteStartSec=item.startTime+(note.start_beat||0)*secondsPerBeat;const noteDurSec=(note.duration_beats||1)*secondsPerBeat;const noteEndSec=noteStartSec+noteDurSec;if(offsetTime{if(st.type!=='PIANO_ROLL')return;const context=getAudioContext();const midiNotes=notesOverride||st.notes||[];const bpmVal=parseInt(bpm)||120;const secondsPerBeat=60.0/bpmVal;const startWallTime=context.currentTime;const track=activeTracksRef.current?activeTracksRef.current.find(t=>t.id===st.trackId):null;const destNode=getOrCreateTrackNode(track,context);const instrumentProgram=track?track.instrumentProgram:undefined;midiNotes.forEach(note=>{const noteOnBeat=note.start_beat||0;const noteDurBeat=note.duration_beats||1;const noteStartSec=noteOnBeat*secondsPerBeat;const noteDurSec=noteDurBeat*secondsPerBeat;if(noteStartSec+noteDurSec>offsetSeconds){const effectiveStart=Math.max(0,noteStartSec-offsetSeconds);const effectiveDur=noteDurSec-Math.max(0,offsetSeconds-noteStartSec);const scheduledTime=startWallTime+effectiveStart;const durMs=effectiveDur*1000;if(window.SonicSF){window.SonicSF.playNote(note.pitch||60,note.velocity||0.8,durMs,scheduledTime,instrumentProgram,destNode);}}});};const handlePlayPause=()=>{if(activeTab!=='main'&&!activeTab.startsWith('session_')){// Sub-tab playback transport const st=subTabs.find(s=>s.id===activeTab);if(!st||!st.buffer&&st.type!=='PIANO_ROLL')return;if(st.isPlaying){stopAllPlayback();setSubTabs(prev=>prev.map(s=>s.id===activeTab?{...s,isPlaying:false}:s));}else{stopAllPlayback();const startOffset=st.currentTime||0;if(st.type==='PIANO_ROLL'){schedulePianoRollMidi(st,startOffset);startSubTabPlayback(st,startOffset);}else{startSubTabPlayback(st,startOffset);}setSubTabs(prev=>prev.map(s=>s.id===activeTab?{...s,isPlaying:true,currentTime:startOffset}:s));}return;}const context=getAudioContext();if(isPlaying){stopAllPlayback();}else{startOffsetTimeRef.current=currentTime;startAudioTimeRef.current=context.currentTime;startTrackPlayback(currentTime);setIsPlaying(true);}};handlePlayPauseRef.current=handlePlayPause;const handlePause=()=>{if(isPlaying||subTabs.some(s=>s.isPlaying))stopAllPlayback();};const stopAllPlayback=()=>{activeSourcesRef.current.forEach(src=>{try{src.stop();}catch(e){}});activeSourcesRef.current=[];Object.values(activeTrackNodesRef.current).forEach(n=>{if(n.fxStopFn)n.fxStopFn();});activeTrackNodesRef.current={};if(window.SonicSF){window.SonicSF.stopAll();}setIsPlaying(false);setSubTabs(prev=>prev.map(s=>({...s,isPlaying:false})));};const handleStop=()=>{if(recordingStateRef.current==='RECORDING'||recordingStateRef.current==='COUNT_IN'){stopRecordingTake();return;}stopAllPlayback();if(activeTab!=='main'&&!activeTab.startsWith('session_')){setSubTabs(prev=>prev.map(s=>s.id===activeTab?{...s,currentTime:0}:s));}else{setCurrentTime(0);}};const drawVuMeter=(canvas,db)=>{if(!canvas)return;const ctx=canvas.getContext('2d');if(!ctx)return;const w=canvas.width;const h=canvas.height;ctx.clearRect(0,0,w,h);const minDb=-60;const maxDb=0;const frac=Math.max(0,Math.min(1,(db-minDb)/(maxDb-minDb)));ctx.fillStyle='#18181b';ctx.fillRect(0,0,w,h);const grad=ctx.createLinearGradient(0,0,w,0);grad.addColorStop(0,'#10b981');grad.addColorStop(0.7,'#eab308');grad.addColorStop(0.95,'#ef4444');ctx.fillStyle=grad;ctx.fillRect(0,0,w*frac,h);if(db>=-0.5){ctx.fillStyle='#ff0000';ctx.fillRect(w-6,0,6,h);}};const handleRecordClick=async()=>{if(recordingState==='RECORDING'||recordingState==='COUNT_IN'){await stopRecordingTake();return;}// Check if piano roll tab is active and armed const activePianoRoll=subTabs.find(s=>s.id===activeTab&&s.type==='PIANO_ROLL'&&s.isArmed);if(activePianoRoll&&selectedMidiInputId){setRecordingState('COUNT_IN');const secondsPerBeat=60.0/(parseInt(bpm)||120);const countInDuration=secondsPerBeat*4;const audioCtx=getAudioContext();const now=audioCtx.currentTime;showToast('Metronome Count-in: 4... 3... 2... 1... (MIDI Piano Roll)','info');for(let i=0;i<4;i++){playMetronomeClick(now+i*secondsPerBeat,i===0);}setTimeout(()=>{startPianoRollRecording(activePianoRoll);},countInDuration*1000);return;}const armed=activeTracks.filter(t=>t.isArmed&&t.inputSource?.deviceType&&t.inputSource.deviceType!=='NONE');if(armed.length===0){showToast('Vui lòng Arm (R) ít nhất một track và chọn cổng Input để ghi âm.','warning');return;}setRecordingState('COUNT_IN');const secondsPerBeat=60.0/(parseInt(bpm)||120);const countInDuration=secondsPerBeat*4;const audioCtx=getAudioContext();const now=audioCtx.currentTime;showToast('Metronome Count-in: 4... 3... 2... 1...','info');for(let i=0;i<4;i++){playMetronomeClick(now+i*secondsPerBeat,i===0);}setTimeout(()=>{startRecordingTake(armed);},countInDuration*1000);};const startPianoRollRecording=tab=>{try{const context=getAudioContext();const secondsPerBeat=60.0/(parseInt(bpm)||120);const startTime=currentTime;const startBeat=startTime/secondsPerBeat;nextMetronomeBeatRef.current=Math.ceil(startBeat);const midiRec=new ClientMIDIRecorder(context,parseInt(bpm)||120,4);midiRec.tempTabId=tab.id;midiRec.selectedMidiInputId=selectedMidiInputId||'ALL';midiRec.start(startTime/secondsPerBeat,midiRec.selectedMidiInputId);pianoRollRecorderRef.current=midiRec;activeMIDIRecordersRef.current['piano_roll']=midiRec;setRecStartTimelineTime(startTime);recordingStartTimeRef.current=startTime;setRecordingState('RECORDING');setRecTempMidiNotes([]);const ctx=getAudioContext();const silentBuf=ctx.createBuffer(1,128,ctx.sampleRate);setSubTabs(prev=>prev.map(s=>s.id===tab.id?{...s,buffer:silentBuf,isPlaying:true}:s));startSubTabPlayback({...tab,buffer:silentBuf},startTime);startOffsetTimeRef.current=startTime;startAudioTimeRef.current=context.currentTime;setIsPlaying(true);midiRec.onNoteOn=(pitch,currentBeat)=>{const elapsedBeats=Math.max(0,currentBeat);const sec=elapsedBeats*(60.0/(parseInt(bpm)||120));const activeNotes=Array.from(midiRec.activeNotes.values()).map(n=>({id:'rec_'+n.pitch+'_'+currentBeat,pitch:n.pitch,start_beat:n.start_beat,duration_beats:Math.max(0.125,currentBeat-n.start_beat),velocity:Math.min(1,n.velocity||0.8),pan:0.0}));const rec=midiRec.recordedNotes.map((n,i)=>({id:'rec_'+Date.now()+'_'+i,pitch:n.pitch,start_beat:n.start_beat,duration_beats:n.duration_beats,velocity:Math.min(1,n.velocity||0.8),pan:0.0}));const allNotes=[...rec,...activeNotes];setRecTempMidiNotes(allNotes);setCanvasRedrawCount(n=>n+1);setSubTabs(prev=>prev.map(s=>s.id===tab.id?{...s,currentTime:startTime+sec,isDirty:true}:s));};if(!tab._recordingStarted){tab._recordingStarted=true;}showToast('Recording MIDI to Piano Roll...','info');}catch(err){console.error('startPianoRollRecording error:',err);showToast('Lỗi khi bắt đầu ghi âm Piano Roll: '+err.message,'warning');setRecordingState('IDLE');}};const startRecordingTake=async armedTracks=>{const context=getAudioContext();if(context.state==='suspended'){await context.resume();}setRecordingState('RECORDING');setRecTempMidiNotes([]);setRecTempAudioBuffer(null);const startTimelineTime=currentTime;setRecStartTimelineTime(startTimelineTime);recordingStartTimeRef.current=startTimelineTime;const secondsPerBeat=60.0/(parseInt(bpm)||120);const startBeat=startTimelineTime/secondsPerBeat;nextMetronomeBeatRef.current=Math.ceil(startBeat);activeMIDIRecordersRef.current={};activeAudioRecordersRef.current={};recordingPCMDataRef.current={};startOffsetTimeRef.current=startTimelineTime;startAudioTimeRef.current=context.currentTime;startTrackPlayback(startTimelineTime);setIsPlaying(true);let midiRecList=[];for(let track of armedTracks){if(track.inputSource.deviceType==='MIDI_KEYBOARD'){const midiRec=new ClientMIDIRecorder(context,parseInt(bpm)||120,4);const tempMidiItemId='midi_rec_'+Date.now()+'_'+track.id;midiRec.tempMidiItemId=tempMidiItemId;updateActiveTracks(prev=>prev.map(t=>{if(t.id!==track.id)return t;return{...t,midiItems:[...(t.midiItems||[]),{id:tempMidiItemId,name:'Recording...',startTime:startTimelineTime,duration:4*(secondsPerBeat*4),notes:[]}]};}));midiRec.onNoteOn=(pitch,currentBeat)=>{const canvas=trackVuRefs.current[track.id];if(canvas){drawVuMeter(canvas,0);setTimeout(()=>drawVuMeter(canvas,-60),100);}const elapsedBeats=Math.max(0,currentBeat);const elapsedSec=elapsedBeats*secondsPerBeat;const durationSec=Math.max(4*(secondsPerBeat*4),elapsedSec);const allNotes=[...midiRec.recordedNotes,...Array.from(midiRec.activeNotes.values()).map(n=>({...n,duration_beats:currentBeat-n.start_beat}))];setRecTempMidiNotes(allNotes);setCanvasRedrawCount(n=>n+1);if(midiRec.tempMidiItemId){updateActiveTracks(prev=>prev.map(t=>{if(t.id!==track.id)return t;return{...t,midiItems:t.midiItems.map(m=>m.id===midiRec.tempMidiItemId?{...m,notes:allNotes,duration:durationSec}:m)};}));}};midiRec.onNoteOff=()=>{const currentBeat=(context.currentTime-midiRec.recStartAudioTime-midiRec.latencyCompSec)/(60.0/midiRec.bpm);const elapsedBeats=Math.max(0,currentBeat);const elapsedSec=elapsedBeats*secondsPerBeat;const durationSec=Math.max(4*(secondsPerBeat*4),elapsedSec);const activeNotesArray=Array.from(midiRec.activeNotes.values()).map(n=>({...n,duration_beats:currentBeat-n.start_beat}));const allNotes=[...midiRec.recordedNotes,...activeNotesArray];setRecTempMidiNotes(allNotes);setCanvasRedrawCount(n=>n+1);if(midiRec.tempMidiItemId){updateActiveTracks(prev=>prev.map(t=>{if(t.id!==track.id)return t;return{...t,midiItems:t.midiItems.map(m=>m.id===midiRec.tempMidiItemId?{...m,notes:allNotes,duration:durationSec}:m)};}));}};midiRec.start(startTimelineTime/(secondsPerBeat*4),track.inputSource.deviceId);activeMIDIRecordersRef.current[track.id]=midiRec;midiRecList.push({trackId:track.id,midiRec});}else if(track.inputSource.deviceType==='MICROPHONE'){const audioRec=new ClientAudioRecorder(context);try{await audioRec.initializeInput(track.inputSource.deviceId);recordingPCMDataRef.current[track.id]=[];audioRec.onLevelUpdate=db=>{const canvas=trackVuRefs.current[track.id];if(canvas){drawVuMeter(canvas,db);}};audioRec.onPCMChunk=chunk=>{if(recordingPCMDataRef.current[track.id]){const currentData=recordingPCMDataRef.current[track.id];const newData=new Float32Array(currentData.length+chunk.length);newData.set(currentData);newData.set(chunk,currentData.length);recordingPCMDataRef.current[track.id]=newData;}};const monitorGain=track.monitoringEnabled?context.destination:null;await audioRec.start(monitorGain,track.monitoringEnabled);activeAudioRecordersRef.current[track.id]=audioRec;}catch(err){console.error('Failed to initialize microphone:',err);showToast('Không khởi động được micro: '+err.message,'warning');}}}recordingSyncRef.current=setInterval(()=>{const secondsPerBeatInt=60.0/(parseInt(bpm)||120);for(let{trackId,midiRec}of midiRecList){if(!midiRec.isRecording||!midiRec.tempMidiItemId)continue;const currentTimeSec=Math.max(0,getAudioContext().currentTime-midiRec.recStartAudioTime-midiRec.latencyCompSec);const currentBeat=currentTimeSec/secondsPerBeatInt;const allNotes=[...midiRec.recordedNotes,...Array.from(midiRec.activeNotes.values()).map(n=>({...n,duration_beats:currentBeat-n.start_beat}))];const durationSec=Math.max(4*(secondsPerBeatInt*4),currentTimeSec);if(Math.random()<0.2){// Throttle log to prevent flooding (approx 2 logs/sec) console.log(`[DevLog] [MIDI Rec Sync] Temp Item ID: ${midiRec.tempMidiItemId}, Duration: ${durationSec.toFixed(2)}s, ActiveNotes: ${midiRec.activeNotes.size}, RecordedNotes: ${midiRec.recordedNotes.length}`);}setRecTempMidiNotes(allNotes);setCanvasRedrawCount(n=>n+1);updateActiveTracks(prev=>prev.map(t=>{if(t.id!==trackId)return t;return{...t,midiItems:t.midiItems.map(m=>m.id===midiRec.tempMidiItemId?{...m,notes:allNotes,duration:durationSec}:m)};}));}},100);showToast('Đang ghi âm...','info');};const stopRecordingTake=async()=>{setRecordingState('IDLE');stopAllPlayback();const context=getAudioContext();const secondsPerBeat=60.0/(parseInt(bpm)||120);const secondsPerBar=secondsPerBeat*4;const midiRecorders=activeMIDIRecordersRef.current;const audioRecorders=activeAudioRecordersRef.current;Object.keys(trackVuRefs.current).forEach(tid=>{const canvas=trackVuRefs.current[tid];if(canvas)drawVuMeter(canvas,-60);});let hasRecordedAnything=false;for(let trackId in midiRecorders){const midiRec=midiRecorders[trackId];if(midiRec.tempTabId){const recordedNotes=midiRec.stop();if(recordedNotes.length>0){const newNotes=recordedNotes.map((n,i)=>({id:'rec_'+Date.now()+'_'+i,pitch:n.pitch,start_beat:Math.max(0,n.start_beat||0),duration_beats:Math.max(0.125,n.duration_beats||0.25),velocity:Math.min(1,n.velocity||0.8),pan:0.0}));setSubTabs(prev=>prev.map(s=>s.id===midiRec.tempTabId?{...s,notes:[...(s.notes||[]),...newNotes],isDirty:true}:s));setCanvasRedrawCount(n=>n+1);showToast(`Đã ghi ${recordedNotes.length} notes vào Piano Roll.`,'success');}hasRecordedAnything=true;}else if(midiRec.tempMidiItemId){const recCurrentTimeSec=Math.max(0,context.currentTime-midiRec.recStartAudioTime-midiRec.latencyCompSec);const recElapsedBeats=recCurrentTimeSec/(60.0/midiRec.bpm);const totalDurationBeats=Math.max(4.0,recordedNotes.length>0?Math.max(recElapsedBeats,...recordedNotes.map(n=>n.start_beat+n.duration_beats)):recElapsedBeats);updateActiveTracks(prev=>prev.map(t=>{if(t.id!==trackId)return t;const itemIndex=(t.midiItems||[]).findIndex(m=>m.id===midiRec.tempMidiItemId);if(itemIndex>=0){const updatedItems=[...t.midiItems];updatedItems[itemIndex]={...updatedItems[itemIndex],name:recordedNotes.length>0?'Recorded MIDI':'Empty MIDI',notes:recordedNotes,duration:Math.ceil(totalDurationBeats/4)*secondsPerBar};return{...t,midiItems:updatedItems};}const newMidiItem={id:'midi_rec_'+Date.now(),name:'Recorded MIDI',startTime:recordingStartTimeRef.current,duration:Math.ceil(totalDurationBeats/4)*secondsPerBar,notes:recordedNotes};return{...t,midiItems:[...(t.midiItems||[]),newMidiItem]};}));if(recordedNotes.length>0){hasRecordedAnything=true;}}else if(recordedNotes.length>0){hasRecordedAnything=true;const totalDurationBeats=Math.max(4.0,...recordedNotes.map(n=>n.start_beat+n.duration_beats));const newMidiItem={id:'midi_rec_'+Date.now(),name:'Recorded MIDI',startTime:recordingStartTimeRef.current,duration:Math.ceil(totalDurationBeats/4)*secondsPerBar,notes:recordedNotes};updateActiveTracks(prev=>prev.map(t=>{if(t.id!==trackId)return t;return{...t,midiItems:[...(t.midiItems||[]),newMidiItem]};}));}}for(let trackId in audioRecorders){const audioRec=audioRecorders[trackId];const audioBuffer=await audioRec.stop();if(audioBuffer&&audioBuffer.duration>0.05){hasRecordedAnything=true;const newClip={id:'clip_rec_'+Date.now(),name:'Recorded Audio.wav',buffer:audioBuffer,startTime:recordingStartTimeRef.current,speed:1.0};updateActiveTracks(prev=>prev.map(t=>{if(t.id!==trackId)return t;const updatedClips=[...(t.clips||[]),newClip];return{...t,clips:updatedClips,buffer:updatedClips[0]?.buffer||null,startTime:updatedClips[0]?.startTime||0,name:updatedClips[0]?.name||t.name};}));}}if(recordingSyncRef.current){clearInterval(recordingSyncRef.current);recordingSyncRef.current=null;}activeMIDIRecordersRef.current={};activeAudioRecordersRef.current={};recordingPCMDataRef.current={};setRecTempMidiNotes([]);setRecTempAudioBuffer(null);if(hasRecordedAnything){showToast('Đã thu và lưu bản ghi vào timeline.','success');}else{showToast('Đã dừng ghi âm (không phát hiện tín hiệu đầu vào).','info');}};const handleSubTabResizeMouseDown=e=>{e.preventDefault();e.stopPropagation();const startY=e.clientY;const startHeight=subTabHeight;const handleMouseMove=moveEvent=>{const deltaY=moveEvent.clientY-startY;const newHeight=Math.max(48,Math.min(400,startHeight+deltaY));setSubTabHeight(newHeight);};const handleMouseUp=()=>{document.removeEventListener('mousemove',handleMouseMove);document.removeEventListener('mouseup',handleMouseUp);};document.addEventListener('mousemove',handleMouseMove);document.addEventListener('mouseup',handleMouseUp);};// ── Playhead set with seek+play ── @@ -379,5 +379,5 @@ const handleSplitTrackAtTime=(trackId,clipId,time)=>{const track=tracks.find(t=> const handleGlueTracks=()=>{const track=tracks.find(t=>t.id===selectedTrackId);if(!track){showToast('Vui lòng chọn một track để thực hiện gộp (glue).','warning');return;}const clips=track.clips&&track.clips.length>0?track.clips:track.buffer?[{id:'default',buffer:track.buffer,startTime:track.startTime||0,name:track.name}]:[];if(clips.length<2){showToast('Cần ít nhất 2 clip trên track này để gộp (glue).','warning');return;}const beforeSnap=captureTrackSnapshot(track.id);const ctx=getAudioContext();const sr=clips[0].buffer.sampleRate;let minStart=Infinity;let maxEnd=-Infinity;clips.forEach(c=>{const start=c.startTime||0;const end=start+c.buffer.duration;minStart=Math.min(minStart,start);maxEnd=Math.max(maxEnd,end);});const newDur=maxEnd-minStart;const newBuffer=ctx.createBuffer(1,Math.ceil(newDur*sr),sr);const newData=newBuffer.getChannelData(0);clips.forEach(c=>{const data=c.buffer.getChannelData(0);const offset=Math.floor(((c.startTime||0)-minStart)*sr);for(let i=0;imaxPeak)maxPeak=abs;}if(maxPeak>1.0){for(let i=0;iprev.map(t=>{if(t.id===track.id){return{...t,clips:[mergedClip],buffer:newBuffer,startTime:minStart,name:mergedClip.name};}return t;}));setTimeout(()=>{const afterSnap=captureTrackSnapshot(track.id);pushAction('GLUE',track.id,beforeSnap,afterSnap);},50);showToast(`Đã gộp ${clips.length} clips thành công.`,'success');};// ── DAW Command Registration for AI (28_AI_PANEL.md §1 & §2) ── useEffect(()=>{if(typeof window.DAWCommandDispatcher==='undefined')return;const api={createTrack:args=>{const name=args.name||`AI_Track_${Date.now()}`;const type=args.type||'audio';const newId=addNewTrack();if(name&&name!==`AI_Track_${Date.now()}`){updateTrackName(newId,name);}return{success:true,trackId:newId,name};},deleteTrack:args=>{const tid=args.track_id||selectedTrackId;if(!tid)return{success:false,error:'No track_id provided'};deleteTrack(tid);return{success:true,trackId:tid};},addClip:args=>{const trackId=args.track_id||selectedTrackId;const barDur=60/parseInt(bpm||120)*4;let startTime;if(args.start_time!==undefined&&args.start_time!==null)startTime=args.start_time;else if(args.start_bar!==undefined&&args.start_bar!==null)startTime=args.start_bar*barDur;else startTime=currentTime;const track=tracks.find(t=>t.id===trackId);if(!track)return{success:false,error:'Track not found'};const ctx=getAudioContext();const sr=44100;let duration;if(args.duration_seconds!==undefined&&args.duration_seconds!==null)duration=args.duration_seconds;else if(args.length_bars!==undefined&&args.length_bars!==null)duration=args.length_bars*barDur;else duration=2;const buffer=ctx.createBuffer(1,Math.floor(sr*duration),sr);const data=buffer.getChannelData(0);for(let i=0;iprev.map(t=>{if(t.id!==trackId)return t;const clips=t.clips&&t.clips.length>0?t.clips:t.buffer?[{id:'default_'+t.id,buffer:t.buffer,startTime:t.startTime||0,name:t.name}]:[];return{...t,clips:[...clips,{id:clipId,buffer,startTime,name:args.name||'AI Clip'}],buffer:clips.length>0?clips[0].buffer:buffer,startTime:clips.length>0?clips[0].startTime:startTime,name:clips.length>0?clips[0].name:args.name||t.name};}));return{success:true,clipId,trackId};},removeClip:args=>{const trackId=args.track_id||selectedTrackId;const clipId=args.clip_id;setTracks(prev=>prev.map(t=>{if(t.id!==trackId)return t;const updatedClips=(t.clips||[]).filter(c=>c.id!==clipId);return{...t,clips:updatedClips,buffer:updatedClips[0]?.buffer||null,startTime:updatedClips[0]?.startTime||0,name:updatedClips[0]?.name||t.name};}));return{success:true};},setTrackVolume:args=>{const trackId=args.track_id||selectedTrackId;const vol=args.volume_db??args.volume??0;updateTrackVolumeDb(trackId,parseFloat(vol));return{success:true,trackId,volumeDb:vol};},setTrackPan:args=>{const trackId=args.track_id||selectedTrackId;const pan=args.pan??0;updateTrackPan(trackId,parseInt(pan));return{success:true,trackId,pan};},toggleMute:args=>{const trackId=args.track_id||selectedTrackId;toggleTrackMute(trackId);const track=tracks.find(t=>t.id===trackId);return{success:true,trackId,muted:track?track.muted:null};},toggleSolo:args=>{const trackId=args.track_id||selectedTrackId;toggleTrackSoloEvaluate(trackId);const track=tracks.find(t=>t.id===trackId);return{success:true,trackId,solo:track?track.solo:null};},processAudioDsp:args=>{const trackId=args.track_id||selectedTrackId;const action=args.action;const params=args.params||{};const track=tracks.find(t=>t.id===trackId);if(!track||!track.buffer)return{success:false,error:'Track has no audio buffer'};if(action==='normalize'){const channelData=track.buffer.getChannelData(0);let maxVal=0;for(let i=0;i0){const gain=1.0/maxVal;for(let i=0;i{const newLen=Math.round(data.length*r);const out=new Float32Array(newLen);for(let i=0;iprev.map(t=>t.id===trackId?{...t,buffer:newBuffer}:t));return{success:true,action:'pitch_shift',semitones};}return{success:false,error:`Unknown action: ${action}`};},renameTrack:args=>{const tid=args.track_id||selectedTrackId;const name=args.name;if(!tid)return{success:false,error:'No track_id provided'};if(!name)return{success:false,error:'No name provided'};updateTrackName(tid,name);return{success:true,trackId:tid,name};},setSelection:args=>{const barDur=60/parseInt(bpm||120)*4;let start,end;if(args.start_time!==undefined&&args.start_time!==null)start=args.start_time;else if(args.start_bar!==undefined&&args.start_bar!==null)start=args.start_bar*barDur;else start=currentTime;if(args.end_time!==undefined&&args.end_time!==null)end=args.end_time;else if(args.length_bars!==undefined&&args.length_bars!==null)end=start+args.length_bars*barDur;else if(args.end_bar!==undefined&&args.end_bar!==null)end=args.end_bar*barDur;else end=start+barDur;clearLocalSelection();setSelectionMode('global');setSelectionStart(start);setSelectionEnd(end);selectionRef.current={start,end};return{success:true,start:parseFloat(start.toFixed(3)),end:parseFloat(end.toFixed(3)),length:parseFloat((end-start).toFixed(3))};},cutAudio:args=>{const currentTracks=window.DAWCommandDispatcher?.currentTracks||tracks;const currentSelTrackId=window.DAWCommandDispatcher?.currentSelectedTrackId||selectedTrackId;const tid=args.track_id||currentSelTrackId;const track=currentTracks.find(t=>t.id===String(tid));if(!track)return{success:false,error:'Track not found'};if(!track.buffer)return{success:false,error:'Track has no audio buffer'};const barDur=60/parseInt(bpm||120)*4;const sel=selectionRef.current;let rawStart,rawEnd;if(args.start_time!==undefined&&args.start_time!==null)rawStart=args.start_time;else if(args.start_bar!==undefined&&args.start_bar!==null)rawStart=args.start_bar*barDur;else if(sel.start!==null)rawStart=sel.start;else rawStart=currentTime;if(args.end_time!==undefined&&args.end_time!==null)rawEnd=args.end_time;else if(args.end_bar!==undefined&&args.end_bar!==null)rawEnd=args.end_bar*barDur;else if(args.length_bars!==undefined&&args.length_bars!==null)rawEnd=rawStart+args.length_bars*barDur;else if(sel.end!==null&&sel.end>rawStart)rawEnd=sel.end;else return{success:false,error:'No end position provided. Provide end_time, end_bar, or length_bars.'};if(rawEnd<=rawStart)return{success:false,error:'End position must be after start position.'};const buffer=track.buffer;const ctx=getAudioContext();const snap=args.snap_silence!==false;const loopStart=snap?findZeroCrossing(buffer,rawStart):rawStart;const loopEnd=snap?findZeroCrossing(buffer,rawEnd):rawEnd;const sampleRate=buffer.sampleRate;const startSample=Math.max(0,Math.min(buffer.length-1,Math.floor(loopStart*sampleRate)));const endSample=Math.max(0,Math.min(buffer.length,Math.floor(loopEnd*sampleRate)));const sliceLength=endSample-startSample;if(sliceLength<=100)return{success:false,error:'Selection too short or invalid'};const numChannels=buffer.numberOfChannels||1;const slicedBuffer=ctx.createBuffer(numChannels,sliceLength,sampleRate);for(let c=0;ct.id===tid);const nextTracks=[...currentTracks];if(idx!==-1){nextTracks.splice(idx+1,0,newTrack);}else{nextTracks.push(newTrack);}if(window.DAWCommandDispatcher){window.DAWCommandDispatcher.currentTracks=nextTracks;window.DAWCommandDispatcher.currentSelectedTrackId=newId;window.DAWCommandDispatcher.lastCutSourceTrackId=tid;window.DAWCommandDispatcher.lastCutNewTrackId=newId;}setTracks(nextTracks);setSelectedTrackId(newId);selectionRef.current={start:0,end:slicedBuffer.duration};clearLocalSelection();setSelectionMode('global');setSelectionStart(0);setSelectionEnd(slicedBuffer.duration);setTimeout(()=>lucide.createIcons(),200);return{success:true,trackId:newId,trackName:cutName,cutStart:parseFloat(loopStart.toFixed(3)),cutEnd:parseFloat(loopEnd.toFixed(3)),duration:parseFloat(slicedBuffer.duration.toFixed(3))};},scanTrack:args=>{const tid=args.track_id||selectedTrackId;const track=tracks.find(t=>t.id===tid);if(!track)return{success:false,error:'Track not found'};if(!track.buffer)return{success:false,error:'Track has no audio buffer. Load audio first.'};const buffer=track.buffer;const data=buffer.getChannelData(0);const sr=buffer.sampleRate;const channels=buffer.numberOfChannels;const duration=buffer.duration;const totalSamples=buffer.length;const windowSize=Math.min(sr*3,data.length);let detectedBPM=0;if(windowSize>sr){let maxCorr=0;for(let lag=Math.floor(sr*0.3);lag<=Math.floor(sr*2.0);lag++){let corr=0;const step=4;for(let i=0;imaxCorr){maxCorr=corr;detectedBPM=60/(lag/sr);}}}detectedBPM=Math.round(Math.min(300,Math.max(30,detectedBPM)));if(args.set_tempo!==false&&detectedBPM>0){setBpm(String(detectedBPM));}const bitDepth=16;const bitrate=Math.round(sr*channels*bitDepth/1000);return{success:true,trackId:tid,trackName:track.name,bpm:detectedBPM,sampleRate:sr,channels,duration:parseFloat(duration.toFixed(3)),totalSamples,bitDepth,bitrateKbps:bitrate,hasAudio:true};},setBpm:args=>{const bpmVal=args.bpm||args.tempo||120;setBpm(String(bpmVal));return{success:true,bpm:bpmVal};},setPlayhead:args=>{const barDur=60/parseInt(bpm||120)*4;let time;if(args.time!==undefined&&args.time!==null)time=args.time;else if(args.bar!==undefined&&args.bar!==null)time=args.bar*barDur;else time=0;handlePlayheadSet(time);return{success:true,time:parseFloat(time.toFixed(3))};},exportAudio:async args=>{const currentTracks=window.DAWCommandDispatcher?.currentTracks||tracks;const currentSelTrackId=window.DAWCommandDispatcher?.currentSelectedTrackId||selectedTrackId;let tid=args.track_id;if(tid&&window.DAWCommandDispatcher?.lastCutSourceTrackId&&(String(tid)===String(window.DAWCommandDispatcher.lastCutSourceTrackId)||'track_'+tid===String(window.DAWCommandDispatcher.lastCutSourceTrackId))){tid=window.DAWCommandDispatcher.lastCutNewTrackId;}if(!tid)tid=currentSelTrackId;const track=tid&¤tTracks.find(t=>t.id===String(tid)||t.id==='track_'+tid);if(!track)return{success:false,error:'No track found'};const clips=track.clips&&track.clips.length>0?track.clips:track.buffer?[{id:'default_'+track.id,buffer:track.buffer,startTime:track.startTime||0,name:track.name}]:[];if(clips.length===0&&(!track.midiItems||track.midiItems.length===0))return{success:false,error:'Track has no audio clips'};const beatsPerSec=parseFloat(bpm||120)/60;const totalDuration=Math.max(clips.length>0?Math.max(...clips.map(c=>(c.startTime||0)+(c.buffer?c.buffer.duration/(c.speed||1.0):0))):0,...(track.midiItems||[]).map(m=>(m.startTime||0)+(m.duration||4)),...(track.sections||[]).map(s=>(s.start||0)+(s.duration||4)));const barDur=60/parseInt(bpm||120)*4;const sel=selectionRef.current;let rawStart,rawEnd;if(args.start_time!==undefined)rawStart=args.start_time;else if(args.start_bar!==undefined)rawStart=args.start_bar*barDur;else if(sel.start!==null)rawStart=sel.start;else rawStart=0;if(args.end_time!==undefined)rawEnd=args.end_time;else if(args.length_bars!==undefined)rawEnd=(rawStart||0)+args.length_bars*barDur;else if(args.end_bar!==undefined)rawEnd=args.end_bar*barDur;else if(sel.end!==null&&sel.end>rawStart)rawEnd=sel.end;else rawEnd=totalDuration;if(rawEnd<=rawStart)return{success:false,error:'Export range is empty or invalid.'};const ctx=getAudioContext();const sr=parseInt(args.sample_rate||'44100');const firstBuffer=clips.find(c=>c.buffer)?.buffer;const numCh=args.channels==='mono'?1:firstBuffer?firstBuffer.numberOfChannels:2;const bd=parseInt(args.bit_depth||'16');const fmt=args.format||'wav';const renderLength=rawEnd-rawStart;const offlineCtx=new OfflineAudioContext(numCh,Math.ceil(sr*renderLength),sr);clips.forEach(clip=>{if(!clip.buffer)return;const clipStart=clip.startTime||0;const clipDuration=clip.buffer.duration/(clip.speed||1.0);const clipEnd=clipStart+clipDuration;if(clipEnd<=rawStart||clipStart>=rawEnd)return;const source=offlineCtx.createBufferSource();source.buffer=clip.buffer;source.playbackRate.value=clip.speed||1.0;source.connect(offlineCtx.destination);if(rawStart{for(let i=0;i>8&0xFF);vw.setUint8(ofs+2,v24>>16&0xFF);}ofs+=bps;}}const blob=new Blob([fileBuf],{type:'audio/wav'});const localUrl=URL.createObjectURL(blob);const targetFilename=`export_${Date.now()}.${fmt}`;const triggerDownload=(downloadUrl,finalFilename)=>{if(window.DAWCommandDispatcher?.isExecutingAI){showToast(`Xuất nhạc thành công (${fmt.toUpperCase()})!`,"success","Tải về",()=>{const a=document.createElement('a');a.href=downloadUrl;a.download=finalFilename;a.click();if(downloadUrl.startsWith('blob:')){URL.revokeObjectURL(downloadUrl);}});}else{const a=document.createElement('a');a.href=downloadUrl;a.download=finalFilename;a.click();showToast("Xuất bản âm thanh hoàn tất!","success");if(downloadUrl.startsWith('blob:')){URL.revokeObjectURL(downloadUrl);}}};if((fmt==='mp3'||fmt==='ogg')&&serverStatus==='connected'){try{const file=new File([blob],`export_ai.wav`,{type:'audio/wav'});const formData=new FormData();formData.append('file',file);const uploadResp=await fetch(`${API_AUDIO}/upload`,{method:'POST',body:formData});if(!uploadResp.ok)throw new Error("Upload failed");const uploadData=await uploadResp.json();const uploadId=uploadData.file_id;const exportResp=await fetch(`${API_AUDIO}/export`,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({file_id:uploadId,format:fmt,sample_rate:sr,bit_depth:bd})});if(!exportResp.ok)throw new Error("Export failed");const exportData=await exportResp.json();const result=await pollTaskResult(exportData.task_id,20);if(result.success){const downloadUrl=`${API_AUDIO}/download/${result.output_file_id}`;triggerDownload(downloadUrl,targetFilename);}else{throw new Error(result.error||'Server encoding failed');}}catch(transcodeErr){showToast(`Lỗi chuyển đổi: ${transcodeErr.message}. Tải về dạng WAV thay thế.`,"warning");triggerDownload(localUrl,`export_${Date.now()}.wav`);}}else{const finalFilename=fmt==='wav'?`export_${Date.now()}.wav`:`export_${Date.now()}.wav`;if(fmt!=='wav'){showToast("Đang ngoại tuyến. Tải về định dạng WAV thay thế.","warning");}triggerDownload(localUrl,finalFilename);}return{success:true,trackId:tid,range:parseFloat((rawEnd-rawStart).toFixed(3))+'s',format:fmt,channels:numCh===1?'mono':'stereo'};},selectItem:args=>{if(args.select_all){setSelectedTrackId(null);clearLocalSelection();setSelectionMode('global');setSelectionStart(0);const maxDur=tracks.reduce((max,t)=>{const dur=t.buffer?t.buffer.duration:0;const clips=t.clips||[];const clipMax=clips.reduce((m,c)=>Math.max(m,(c.startTime||0)+(c.buffer?c.buffer.duration:0)),0);return Math.max(max,dur,clipMax);},0);setSelectionEnd(Math.max(maxDur,currentTime+10));return{success:true,selection:'all',duration:parseFloat(Math.max(maxDur,currentTime+10).toFixed(3))};}const tid=args.track_id||selectedTrackId;const track=tracks.find(t=>t.id===tid);if(!track)return{success:false,error:`Track ${tid} not found`};const clips=track.clips&&track.clips.length>0?track.clips:track.buffer?[{id:'default_'+track.id,name:track.name,buffer:track.buffer,startTime:track.startTime||0}]:[];if(args.item_name){const match=clips.find(c=>c.name&&c.name.toLowerCase().includes(args.item_name.toLowerCase()));if(!match)return{success:false,error:`No clip matching "${args.item_name}" on track ${track.name}`};setSelectedTrackId(tid);clearLocalSelection();setSelectionMode('global');const start=match.startTime||0;const end=start+(match.buffer?match.buffer.duration:2);setSelectionStart(start);setSelectionEnd(end);return{success:true,trackId:tid,trackName:track.name,clipId:match.id,clipName:match.name,start:parseFloat(start.toFixed(3)),end:parseFloat(end.toFixed(3))};}setSelectedTrackId(tid);clearLocalSelection();setSelectionMode('global');const trackEnd=track.buffer?track.buffer.duration:clips.length>0?Math.max(...clips.map(c=>(c.startTime||0)+(c.buffer?c.buffer.duration:0))):4;setSelectionStart(0);setSelectionEnd(trackEnd);return{success:true,trackId:tid,trackName:track.name,duration:parseFloat(trackEnd.toFixed(3))};},addMarker:args=>{const trackId=args.track_id||selectedTrackId;const time=args.time??currentTime;const track=tracks.find(t=>t.id===trackId);if(!track)return{success:false,error:'Track not found'};setTracks(prev=>prev.map(t=>{if(t.id!==trackId)return t;return{...t,markers:[...(t.markers||[]),{id:'ai_marker_'+Date.now(),time,label:args.label||'AI Marker'}]};}));return{success:true,trackId,time};},fadeIn:args=>{const currentTracks=window.DAWCommandDispatcher?.currentTracks||tracks;const currentSelTrackId=window.DAWCommandDispatcher?.currentSelectedTrackId||selectedTrackId;let trackIdRaw=args.track_id;if(trackIdRaw&&window.DAWCommandDispatcher?.lastCutSourceTrackId&&(String(trackIdRaw)===String(window.DAWCommandDispatcher.lastCutSourceTrackId)||'track_'+trackIdRaw===String(window.DAWCommandDispatcher.lastCutSourceTrackId))){trackIdRaw=window.DAWCommandDispatcher.lastCutNewTrackId;}if(!trackIdRaw)trackIdRaw=currentSelTrackId;const track=currentTracks.find(t=>t.id===String(trackIdRaw)||t.id==='track_'+trackIdRaw);if(!track)return{success:false,error:`Track ${trackIdRaw} not found`};const clips=track.clips&&track.clips.length>0?track.clips:track.buffer?[{id:'default_'+track.id,buffer:track.buffer,startTime:track.startTime||0,name:track.name}]:[];if(clips.length===0)return{success:false,error:'No clips on track'};let clip=null;if(args.clip_id){clip=clips.find(c=>c.id===args.clip_id);}else if(args.clip_index!==undefined){const idx=parseInt(args.clip_index);const realIdx=idx>0?idx-1:0;clip=clips[realIdx]||clips[0];}else{clip=clips[0];}if(!clip||!clip.buffer)return{success:false,error:'Clip has no audio buffer'};const duration=parseFloat(args.duration_seconds||3);const buffer=clip.buffer;const sr=buffer.sampleRate;const numChannels=buffer.numberOfChannels;const length=buffer.length;const ctx=getAudioContext();const newBuffer=ctx.createBuffer(numChannels,length,sr);for(let c=0;c{if(t.id!==track.id)return t;const existingClips=t.clips&&t.clips.length>0?t.clips:t.buffer?[{id:'default_'+t.id,buffer:t.buffer,startTime:t.startTime||0,name:t.name}]:[];const updatedClips=existingClips.map(c=>{if(c.id===clip.id||clip.id.startsWith('default_')&&c.id==='default'){return{...c,buffer:newBuffer};}return c;});const mainBuffer=updatedClips[0]?.buffer||t.buffer;return{...t,clips:updatedClips,buffer:mainBuffer};});if(window.DAWCommandDispatcher){window.DAWCommandDispatcher.currentTracks=nextTracks;}setTracks(nextTracks);setTimeout(()=>{const afterSnap=captureTrackSnapshot(track.id);pushAction('AI_FADE_IN',track.id,beforeSnap,afterSnap);},50);return{success:true,trackId:track.id,clipId:clip.id,duration_seconds:duration};},fadeOut:args=>{const currentTracks=window.DAWCommandDispatcher?.currentTracks||tracks;const currentSelTrackId=window.DAWCommandDispatcher?.currentSelectedTrackId||selectedTrackId;let trackIdRaw=args.track_id;if(trackIdRaw&&window.DAWCommandDispatcher?.lastCutSourceTrackId&&(String(trackIdRaw)===String(window.DAWCommandDispatcher.lastCutSourceTrackId)||'track_'+trackIdRaw===String(window.DAWCommandDispatcher.lastCutSourceTrackId))){trackIdRaw=window.DAWCommandDispatcher.lastCutNewTrackId;}if(!trackIdRaw)trackIdRaw=currentSelTrackId;const track=currentTracks.find(t=>t.id===String(trackIdRaw)||t.id==='track_'+trackIdRaw);if(!track)return{success:false,error:`Track ${trackIdRaw} not found`};const clips=track.clips&&track.clips.length>0?track.clips:track.buffer?[{id:'default_'+track.id,buffer:track.buffer,startTime:track.startTime||0,name:track.name}]:[];if(clips.length===0)return{success:false,error:'No clips on track'};let clip=null;if(args.clip_id){clip=clips.find(c=>c.id===args.clip_id);}else if(args.clip_index!==undefined){const idx=parseInt(args.clip_index);const realIdx=idx>0?idx-1:0;clip=clips[realIdx]||clips[0];}else{clip=clips[0];}if(!clip||!clip.buffer)return{success:false,error:'Clip has no audio buffer'};const duration=parseFloat(args.duration_seconds||3);const buffer=clip.buffer;const sr=buffer.sampleRate;const numChannels=buffer.numberOfChannels;const length=buffer.length;const ctx=getAudioContext();const newBuffer=ctx.createBuffer(numChannels,length,sr);for(let c=0;c{if(t.id!==track.id)return t;const existingClips=t.clips&&t.clips.length>0?t.clips:t.buffer?[{id:'default_'+t.id,buffer:t.buffer,startTime:t.startTime||0,name:t.name}]:[];const updatedClips=existingClips.map(c=>{if(c.id===clip.id||clip.id.startsWith('default_')&&c.id==='default'){return{...c,buffer:newBuffer};}return c;});const mainBuffer=updatedClips[0]?.buffer||t.buffer;return{...t,clips:updatedClips,buffer:mainBuffer};});if(window.DAWCommandDispatcher){window.DAWCommandDispatcher.currentTracks=nextTracks;}setTracks(nextTracks);setTimeout(()=>{const afterSnap=captureTrackSnapshot(track.id);pushAction('AI_FADE_OUT',track.id,beforeSnap,afterSnap);},50);return{success:true,trackId:track.id,clipId:clip.id,duration_seconds:duration};},generateMultitrackMidi:args=>{const{composition_title,bpm:aiBpm,total_bars,tracks:aiTracks}=args;if(aiBpm){setBpm(aiBpm.toString());}const bpmVal=aiBpm||parseInt(bpm)||120;const secondsPerBeat=60.0/bpmVal;const secondsPerBar=secondsPerBeat*4;const durationSec=total_bars*secondsPerBar;updateActiveTracks(prev=>{let updatedTracks=[...prev];aiTracks.forEach(aiTrack=>{let targetTrack=updatedTracks.find(t=>t.name.toLowerCase()===aiTrack.track_name.toLowerCase());if(!targetTrack){const newId=(updatedTracks.length+1).toString();const colors=['#0f766e','#1d4ed8','#701a75','#a21caf','#b45309'];const selectColor=colors[updatedTracks.length%colors.length];targetTrack={id:newId,name:aiTrack.track_name,type:'MIDI',volumeDb:0,pan:0,muted:false,solo:false,color:selectColor,markers:[],serverFileId:null,clips:[],sections:[],midiItems:[],isArmed:false,monitoringEnabled:true,inputSource:{deviceType:'NONE',deviceId:''}};updatedTracks.push(targetTrack);}const itemStartTimeSec=currentTime;const newMidiItem={id:'item_ai_'+Date.now()+'_'+Math.random().toString(36).substr(2,5),name:`${composition_title||'AI Theme'} - ${aiTrack.track_name}`,startTime:itemStartTimeSec,duration:durationSec,notes:aiTrack.notes.map((note,index)=>({id:`note_ai_${Date.now()}_${index}`,pitch:note.pitch,start_beat:note.start_beat,duration_beats:note.duration_beats,velocity:note.velocity||0.8,pan:0.0}))};targetTrack.midiItems=[...(targetTrack.midiItems||[]),newMidiItem];});return updatedTracks;});showToast(`Đã nạp ${aiTracks.length} tracks MIDI thế hệ AI!`,'success');return{success:true};},createMidiItem:args=>{const trackId=args.track_id||selectedTrackId;if(!trackId)return{success:false,error:'No track_id provided'};const secondsPerBar=60.0/(parseInt(bpm)||120)*4;const startBar=args.start_bar!==undefined?parseFloat(args.start_bar):0;const lengthBars=args.length_bars!==undefined?parseFloat(args.length_bars):4;const midiItem={id:`midi_${Date.now()}_${Math.random().toString(36).substr(2,5)}`,name:'MIDI Item',startTime:startBar*secondsPerBar,duration:lengthBars*secondsPerBar,notes:[],color:'#a78bfa'};updateActiveTracks(prev=>prev.map(t=>{if(t.id!==trackId&&t.id!=='track_'+trackId)return t;return{...t,midiItems:[...(t.midiItems||[]),midiItem]};}));return{success:true,itemId:midiItem.id,trackId};},modifyMidiNotes:args=>{const itemId=args.item_id;if(!itemId)return{success:false,error:'No item_id provided'};const noteNameToMidi=name=>{if(typeof name==='number')return name;if(!name||typeof name!=='string')return 60;const match=name.match(/^([A-Ga-g]#?|b?)(-?\d+)$/);if(!match){const num=parseInt(name);return isNaN(num)?60:num;}const noteNames={'c':0,'c#':1,'db':1,'d':2,'d#':3,'eb':3,'e':4,'f':5,'f#':6,'gb':6,'g':7,'g#':8,'ab':8,'a':9,'a#':10,'bb':10,'b':11};const key=match[1].toLowerCase();const octave=parseInt(match[2]);const base=noteNames[key]!==undefined?noteNames[key]:0;return(octave+1)*12+base;};const newNotes=(args.notes||[]).map((n,index)=>({id:`note_mod_${Date.now()}_${index}`,pitch:noteNameToMidi(n.pitch),start_beat:parseFloat(n.start_time||0),duration_beats:parseFloat(n.duration||1),velocity:n.velocity!==undefined?n.velocity/127.0:0.8,pan:0.0}));updateActiveTracks(prev=>prev.map(t=>{const items=t.midiItems||[];const exists=items.some(m=>m.id===itemId);if(!exists)return t;return{...t,midiItems:items.map(m=>m.id===itemId?{...m,notes:newNotes}:m)};}));return{success:true,itemId};}};window.DAWCommandDispatcher.registerDAWCommands(api);},[tracks,selectedTrackId,currentTime,bpm]);// ── Save AI config to localStorage ── useEffect(()=>{localStorage.setItem('ai_base_url',aiConfig.baseUrl);localStorage.setItem('ai_api_key',aiConfig.apiKey);localStorage.setItem('ai_model',aiConfig.model);},[aiConfig]);// ── Auto-save user preferences (panel state, provider) ── -const prefsRef=useRef({});prefsRef.current={showAIPanel,showExportPanel,showSelectionPanel,showPythonToolsPanel,showMediaExplorer,showFxRack,showMidiEvents,panelPositions,rightSidebarWidth,mediaExplorerHeight,selectedProviderId};useEffect(()=>{const prefs=prefsRef.current;localStorage.setItem('sonic_preferences',JSON.stringify(prefs));if(!currentUser||currentUser==='cached')return;const timer=setTimeout(async()=>{try{await window.SonicAPI.savePreferences(prefs);}catch(e){}},2000);return()=>clearTimeout(timer);},[showAIPanel,showExportPanel,showSelectionPanel,showPythonToolsPanel,showMediaExplorer,showFxRack,showMidiEvents,panelPositions,rightSidebarWidth,mediaExplorerHeight,selectedProviderId,currentUser]);return/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{className:"h-full w-full flex flex-col bg-[#1e1e1e]"},/*#__PURE__*/React.createElement("header",{className:"h-9 bg-[#2e2e2e] border-b border-[#181818] flex items-center px-1 shrink-0 select-none"},[{label:'File',items:[{label:'New Project',icon:'file-plus',shortcut:'Ctrl+N',action:()=>{setTracks([{id:'1',name:'Track 01',buffer:null,startTime:0,volumeDb:0,pan:0,muted:false,solo:false,color:'#0f766e',markers:[],serverFileId:null,clips:[],sections:[],midiItems:[]},{id:'2',name:'Track 02',buffer:null,startTime:0,volumeDb:0,pan:0,muted:false,solo:false,color:'#1d4ed8',markers:[],serverFileId:null,clips:[],sections:[],midiItems:[]}]);setSelectedTrackId('1');setProjectName('');setCurrentProjectId(null);localStorage.removeItem('sonic_project_name');localStorage.removeItem('sonic_project_id');showToast('New project created','info');}},{label:'Open Project...',icon:'folder-open',shortcut:'Ctrl+O',action:()=>handleImportSFS()},{label:'Save Project',icon:'upload-cloud',shortcut:'Ctrl+S',action:()=>handleSaveProject()},{label:'Save As...',icon:'download',shortcut:'Ctrl+Alt+S',action:()=>setSaveAsModalOpen(true)},{sep:true},{label:'Config AI Providers...',icon:'settings',action:()=>setAiConfigModalOpen(true)},{label:'Import Audio...',icon:'file-input',shortcut:'Ctrl+Alt+I',action:()=>{const input=document.createElement('input');input.type='file';input.accept='audio/*';input.onchange=async e=>{if(e.target.files[0]){addNewTrack();const newId=(tracks.length+1).toString();setTimeout(()=>loadFileOnTrack(newId,e.target.files[0]),100);}};input.click();showToast('Import audio','info');}},{label:'Export Mix...',icon:'file-output',action:()=>triggerWavExport()},{label:'Export MIDI...',icon:'music',action:()=>triggerMidiExport()},{sep:true},...(currentUser?[{label:'Profile',icon:'user',action:()=>setProfileModalOpen(true)}]:[]),...(currentUser&¤tUser.role==='admin'?[{label:'System Manager',icon:'settings',action:()=>setSystemManagerModalOpen(true)}]:[]),{label:'Logout',icon:'log-out',action:()=>handleLogout()}]},{label:'Edit',items:[{label:'Insert New Track',icon:'plus',shortcut:'Ctrl+I',action:addNewTrack},{label:'Insert Music to Track',icon:'music',shortcut:'Ctrl+Alt+I',action:()=>showToast('Select music file to insert','info')},{sep:true},{label:'Edit in New Tab',icon:'file-edit',shortcut:'Ctrl+E',action:()=>openTempTab()},{label:'Split at Playhead',icon:'scissors',shortcut:'S',action:()=>handleSplitTrack(selectedTrackId)},{label:'Merge Tracks',icon:'combine',shortcut:'Ctrl+M',action:()=>{handleMergeTracks();}},{sep:true},{label:'Undo',icon:'undo',shortcut:'Ctrl+Z',action:()=>{handleUndo();}},{label:'Redo',icon:'redo',shortcut:'Ctrl+Y',action:()=>{handleRedo();}},{sep:true},{label:'Copy',icon:'copy',shortcut:'Ctrl+C',action:()=>{handleCopyTrack();}},{label:'Cut',icon:'scissors',shortcut:'Ctrl+X',action:()=>{handleCutTrack();}},{label:'Paste',icon:'clipboard',shortcut:'Ctrl+V',action:handlePasteTrack},{sep:true},{label:'Delete Track',icon:'trash-2',shortcut:'Del',action:()=>{handleDeleteTrack();}}]},{label:'Insert',items:[...(!sessionTabs.some(s=>s.id===activeTab)?[{label:'Insert Section',icon:'folder-plus',action:insertSectionAtPlayhead}]:[]),{label:'Insert MIDI item',icon:'music',action:insertMidiItemAtPlayhead},{label:'Insert sound clip',icon:'file-input',action:insertSoundClipAtCursor},{label:'Insert track',icon:'plus',action:insertTrackBelow}]},{label:'View',items:[{label:'Master Track',icon:'disc',action:()=>showToast('Master track view','info')},{label:'Maker View',icon:'layout',action:()=>showToast('Maker view','info')},{label:'Mixer',icon:'sliders',action:()=>showToast('Mixer panel','info')},{label:'Tempo Track',icon:'timer',action:()=>showToast('Tempo track','info')},{label:'Video',icon:'film',action:()=>showToast('Video panel','info')},{label:'Media Explorer',icon:'folder-search',action:()=>showToast('Media explorer','info')}]},{label:'Tools',items:[{label:'Config AI Providers...',icon:'settings',action:()=>setAiConfigModalOpen(true)},{label:'AI MIDI Preset Manager...',icon:'sliders',action:()=>setAiPresetModalOpen(true)},{label:'DSP Tools Panel',icon:'wrench',action:()=>openPanel('python_tools')},{sep:true},{label:'Plugin Manager (SoundFont/VSTi)',icon:'zap',action:()=>{setPluginManagerModalOpen(true);window.SonicAPI.listPlugins().then(data=>setPluginsData(data)).catch(()=>{});}}]},{label:'Help',items:[{label:'About SonicForge',icon:'info',action:()=>showToast('SonicForge Studio v1.0 - Professional DAW','info')}]}].map(menu=>/*#__PURE__*/React.createElement("div",{key:menu.label,className:"relative"},/*#__PURE__*/React.createElement("button",{onClick:()=>setMenuOpen(menuOpen===menu.label?null:menu.label),className:`px-3 py-1 text-xs font-medium transition rounded ${menuOpen===menu.label?'bg-zinc-700 text-zinc-100':'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800'}`},menu.label),menuOpen===menu.label&&/*#__PURE__*/React.createElement("div",{className:`absolute top-full left-0 mt-0.5 bg-[#2a2a2a] border border-zinc-700 rounded-lg shadow-2xl py-1 z-50 ${menu.label==='Edit'?'w-72':'w-64'}`,onClick:()=>setMenuOpen(null)},menu.items.map((item,i)=>item.sep?/*#__PURE__*/React.createElement("div",{key:i,className:"h-px bg-zinc-700 my-1"}):/*#__PURE__*/React.createElement("button",{key:item.label,onClick:e=>{e.stopPropagation();item.action();setMenuOpen(null);},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":item.icon,className:"w-3.5 h-3.5 text-zinc-500 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},item.label),item.shortcut&&/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},item.shortcut)))))),/*#__PURE__*/React.createElement("div",{className:"flex-1"}),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2 px-2"},/*#__PURE__*/React.createElement("span",{className:`text-xs font-bold uppercase px-1.5 py-0.5 rounded ${serverStatus==='connected'?'bg-emerald-950 text-emerald-400':serverStatus==='checking'?'bg-amber-950 text-amber-400':'bg-red-950 text-red-400'}`},"Server: ",serverStatus),/*#__PURE__*/React.createElement("button",{onClick:()=>setShowAIConfig(!showAIConfig),className:`px-1.5 py-0.5 rounded text-xs border transition ${showAIConfig?'bg-purple-900 text-purple-200 border-purple-700':'bg-zinc-800 text-zinc-400 border-zinc-700 hover:text-zinc-200'}`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"cpu",className:"w-3 h-3"}))))),menuOpen&&/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-40",onClick:()=>setMenuOpen(null)}),/*#__PURE__*/React.createElement("div",{className:"h-7 bg-[#222] border-b border-zinc-800 flex items-stretch px-2 gap-0.5 shrink-0 overflow-x-auto"},/*#__PURE__*/React.createElement("button",{onClick:()=>setActiveTab('main'),className:`px-3 text-xs font-bold uppercase tracking-wider border-b-2 transition flex items-center gap-1 ${activeTab==='main'?'text-cyan-400 border-cyan-500 bg-zinc-800/50':'text-zinc-500 border-transparent hover:text-zinc-300 hover:bg-zinc-800/30'}`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"layout-dashboard",className:"w-3 h-3"}))," Main Session"),sessionTabs.map(st=>{const isTabActive=activeTab===st.id;const tabColor=st.color||(isTabActive?'#06b6d4':null);const borderStyle=isTabActive?{borderBottomColor:tabColor,color:tabColor}:st.color?{color:st.color,borderBottomColor:'transparent'}:{};return/*#__PURE__*/React.createElement("div",{key:st.id,className:"flex items-stretch"},/*#__PURE__*/React.createElement("button",{onClick:()=>setActiveTab(st.id),onAuxClick:e=>{if(e.button===1){e.preventDefault();closeSessionTab(st.id);}},onContextMenu:e=>{e.preventDefault();setTabContextMenu({x:e.clientX,y:e.clientY,tabId:st.id,tabType:'session'});},style:borderStyle,className:`px-2 text-xs font-medium border-b-2 transition flex items-center gap-1 ${isTabActive?'bg-zinc-800/50':'text-zinc-500 border-transparent hover:text-zinc-300 hover:bg-zinc-800/30'}`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"layers",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"max-w-[120px] truncate"},st.name),st.isDirty&&/*#__PURE__*/React.createElement("span",{className:"w-1.5 h-1.5 rounded-full bg-amber-500 ml-1",title:"Chưa lưu thay đổi"})),/*#__PURE__*/React.createElement("button",{onClick:()=>closeSessionTab(st.id),className:"px-1 text-zinc-600 hover:text-red-400 transition text-xs",title:"Close tab"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"}))));}),subTabs.map(st=>{const isTabActive=activeTab===st.id;const tabColor=st.color||(isTabActive?'#f59e0b':null);const borderStyle=isTabActive?{borderBottomColor:tabColor,color:tabColor}:st.color?{color:st.color,borderBottomColor:'transparent'}:{};const iconName=st.type==='PIANO_ROLL'?'music':'file-edit';return/*#__PURE__*/React.createElement("div",{key:st.id,className:"flex items-stretch"},/*#__PURE__*/React.createElement("button",{onClick:()=>setActiveTab(st.id),onAuxClick:e=>{if(e.button===1){e.preventDefault();closeSubTab(st.id);}},onContextMenu:e=>{e.preventDefault();setTabContextMenu({x:e.clientX,y:e.clientY,tabId:st.id,tabType:'sub'});},style:borderStyle,className:`px-2 text-xs font-medium border-b-2 transition flex items-center gap-1 ${isTabActive?'bg-zinc-800/50':'text-zinc-500 border-transparent hover:text-zinc-300 hover:bg-zinc-800/30'}`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":iconName,className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"max-w-[100px] truncate"},st.label),st.isDirty&&/*#__PURE__*/React.createElement("span",{className:"w-1.5 h-1.5 rounded-full bg-amber-500 ml-1",title:"Chưa lưu thay đổi"})),/*#__PURE__*/React.createElement("button",{onClick:()=>closeSubTab(st.id),className:"px-1 text-zinc-600 hover:text-red-400 transition text-xs",title:"Close tab"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"}))));})),showAIConfig&&/*#__PURE__*/React.createElement("div",{className:"bg-zinc-900 border-b border-purple-900 p-3 flex flex-col gap-2 transition-all"},/*#__PURE__*/React.createElement("div",{className:"text-xs font-bold text-purple-400 uppercase tracking-wider flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"cpu",className:"w-4 h-4"}))," Cấu hình cổng kết nối API"),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-2 text-xs"},/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1"},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500 font-bold uppercase"},"Endpoint Base URL"),/*#__PURE__*/React.createElement("input",{type:"text",value:aiConfig.baseUrl,onChange:e=>setAiConfig(prev=>({...prev,baseUrl:e.target.value})),className:"bg-zinc-850 text-zinc-200 p-1.5 rounded border border-zinc-800 focus:outline-none focus:border-purple-600 font-mono text-xs",placeholder:"https://api.openai.com/v1"})),/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1"},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500 font-bold uppercase"},"API Token Key"),/*#__PURE__*/React.createElement("input",{type:"password",value:aiConfig.apiKey,onChange:e=>setAiConfig(prev=>({...prev,apiKey:e.target.value})),className:"bg-zinc-850 text-zinc-200 p-1.5 rounded border border-zinc-800 focus:outline-none focus:border-purple-600 font-mono text-xs",placeholder:"sk-..."})),/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1"},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500 font-bold uppercase"},"Model Name"),/*#__PURE__*/React.createElement("input",{type:"text",value:aiConfig.model,onChange:e=>setAiConfig(prev=>({...prev,model:e.target.value})),className:"bg-zinc-850 text-zinc-200 p-1.5 rounded border border-zinc-800 focus:outline-none focus:border-purple-600 font-mono text-xs",placeholder:"gpt-4o-mini"})))),/*#__PURE__*/React.createElement("div",{className:"h-9 bg-[#222] border-b border-zinc-800 flex items-center px-3 gap-2 shrink-0 select-none"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1 bg-zinc-900 border border-zinc-700 rounded px-1.5 py-0.5 shadow-lg",title:"Kéo để di chuyển toolbar",style:{cursor:'grab'}},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-0.5 mr-1 text-zinc-600"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{setActiveTool('select');showToast('Select Tool','info');},className:`w-7 h-7 flex items-center justify-center rounded ${activeTool==='select'?'bg-cyan-700 text-white':'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800'}`,title:"Select Tool (V)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"mouse-pointer",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{setActiveTool('grab');showToast('Grab Tool','info');},className:`w-7 h-7 flex items-center justify-center rounded ${activeTool==='grab'?'bg-cyan-700 text-white':'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800'}`,title:"Grab Tool (H)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"hand",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-0.5 border border-zinc-700 rounded bg-zinc-850 px-0.5"},/*#__PURE__*/React.createElement("button",{onClick:()=>{setActiveTool('razor');showToast('Razor Tool','info');},className:`w-7 h-7 flex items-center justify-center rounded ${activeTool==='razor'?'bg-cyan-700 text-white':'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800'}`,title:"Razor Tool (C)"},/*#__PURE__*/React.createElement("svg",{className:"w-3.5 h-3.5 text-orange-400",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round"},/*#__PURE__*/React.createElement("path",{d:"M6 3h12a2 2 0 0 1 2 2v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"}),/*#__PURE__*/React.createElement("path",{d:"M4 9h16l-3 9H7z"}),/*#__PURE__*/React.createElement("circle",{cx:"12",cy:"6",r:"1"}))),/*#__PURE__*/React.createElement("button",{onClick:handleGlueTracks,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-purple-400 hover:bg-zinc-800",title:"Glue Clips"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"link",className:"w-3.5 h-3.5"})))),/*#__PURE__*/React.createElement("button",{onClick:()=>{setActiveTool('pen');showToast('Pen Tool','info');},className:`w-7 h-7 flex items-center justify-center rounded ${activeTool==='pen'?'bg-cyan-700 text-white':'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800'}`,title:"Pen Tool (P)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"pen-tool",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-700 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:handleCutTrack,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-red-400 hover:bg-zinc-800",title:"Cut (Ctrl+X)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:handleCopyTrack,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-blue-400 hover:bg-zinc-800",title:"Copy (Ctrl+C)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"copy",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:handlePasteTrack,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-emerald-400 hover:bg-zinc-800",title:"Paste (Ctrl+V)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"clipboard",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-700 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:addNewTrack,className:"px-2 py-1 bg-cyan-600 hover:bg-cyan-500 text-white font-semibold rounded text-xs flex items-center gap-1 shadow transition",title:"Thêm Track Mới (Ctrl+I)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus",className:"w-3.5 h-3.5"})),/*#__PURE__*/React.createElement("span",null,"Track")),sessionTabs.some(s=>s.id===activeTab)&&/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-700 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:()=>handleSaveSectionTab(activeTab),className:"px-2 py-1 bg-emerald-600 hover:bg-emerald-500 text-white font-semibold rounded text-xs flex items-center gap-1 shadow transition",title:"Lưu Section vào Main Session"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"save",className:"w-3.5 h-3.5"})),/*#__PURE__*/React.createElement("span",null,"Lưu Section"))),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-700 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:handleUndo,disabled:undoStack.length===0,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800 disabled:opacity-30",title:"Undo (Ctrl+Z)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"undo",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:handleRedo,disabled:redoStack.length===0,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800 disabled:opacity-30",title:"Redo (Ctrl+Y)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"redo",className:"w-3.5 h-3.5"})))),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-800 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:()=>{const isSubTab=subTabs.some(sub=>sub.id===activeTab);if(isSubTab){setSubTabs(prev=>prev.map(s=>s.id===activeTab?{...s,currentTime:0}:s));}else{setCurrentTime(0);}},className:"w-7 h-7 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Quay lại đầu"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"skip-back",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{const isSubTab=subTabs.some(sub=>sub.id===activeTab);if(isSubTab){setSubTabs(prev=>prev.map(s=>{if(s.id!==activeTab)return s;const left=s.selectionStart!==null&&s.selectionEnd!==null?Math.min(s.selectionStart,s.selectionEnd):null;return left!==null?{...s,currentTime:left}:s;}));}else{if(selLeft!==null)setCurrentTime(selLeft);}},className:"w-7 h-7 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Đầu vùng chọn"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"step-back",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:handlePlayPause,className:`w-7 h-7 flex items-center justify-center rounded border transition ${isPlaying?'bg-emerald-600 text-black border-emerald-500 hover:bg-emerald-500':'bg-cyan-600 text-white border-cyan-500 hover:bg-cyan-500'}`,title:isPlaying?"Tạm dừng":"Play"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":isPlaying?"pause":"play",className:"w-3.5 h-3.5 fill-current"}))),/*#__PURE__*/React.createElement("button",{onClick:handleStop,className:"w-7 h-7 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Stop"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"square",className:"w-3.5 h-3.5 fill-current"}))),/*#__PURE__*/React.createElement("button",{onClick:handleRecordClick,className:`w-7 h-7 flex items-center justify-center rounded border transition ${recordingState==='RECORDING'?'bg-red-600 text-white border-red-500 hover:bg-red-500 animate-pulse':recordingState==='COUNT_IN'?'bg-amber-500 text-black border-amber-400 hover:bg-amber-400 animate-pulse':'bg-zinc-800 text-red-500 border-zinc-700 hover:bg-zinc-700 hover:text-red-400'}`,title:recordingState==='RECORDING'?"Đang ghi âm...":recordingState==='COUNT_IN'?"Chuẩn bị ghi âm...":"Ghi âm (Record)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"circle",className:"w-3.5 h-3.5 fill-current"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{const isSubTab=subTabs.some(sub=>sub.id===activeTab);if(isSubTab){setSubTabs(prev=>prev.map(s=>{if(s.id!==activeTab)return s;const right=s.selectionStart!==null&&s.selectionEnd!==null?Math.max(s.selectionStart,s.selectionEnd):null;return right!==null?{...s,currentTime:right}:s;}));}else{if(selRight!==null)setCurrentTime(selRight);}},className:"w-7 h-7 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Cuối vùng chọn"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"step-forward",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{const isSubTab=subTabs.some(sub=>sub.id===activeTab);if(isSubTab){setSubTabs(prev=>prev.map(s=>{if(s.id!==activeTab)return s;const duration=s.buffer?s.buffer.duration/(s.speed||1.0):0;return{...s,currentTime:duration};}));}else{setCurrentTime(maxDuration);}},className:"w-7 h-7 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Đến cuối"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"skip-forward",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-800 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:()=>setIsLoopingSelection(prev=>!prev),className:`w-7 h-7 flex items-center justify-center rounded border transition ${isLoopingSelection?'bg-amber-600 text-black border-amber-500 hover:bg-amber-500':'bg-zinc-800 text-zinc-200 border-zinc-700 hover:bg-zinc-700'}`,title:isLoopingSelection?selLeft!==null&&selRight!==null?"Loop vùng chọn":"Loop timeline":"Bật loop"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"repeat",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500 font-bold uppercase ml-2"},"Snap"),/*#__PURE__*/React.createElement("select",{value:snapValue,onChange:e=>setSnapValue(e.target.value),className:"bg-black text-white text-[14px] px-1.5 py-0.5 rounded border border-zinc-700 focus:outline-none focus:border-cyan-500 font-mono cursor-pointer"},/*#__PURE__*/React.createElement("option",{value:"free"},"Free"),/*#__PURE__*/React.createElement("option",{value:"1"},"1"),/*#__PURE__*/React.createElement("option",{value:"1/2"},"1/2"),/*#__PURE__*/React.createElement("option",{value:"1/4"},"1/4"),/*#__PURE__*/React.createElement("option",{value:"1/8"},"1/8"),/*#__PURE__*/React.createElement("option",{value:"1/16"},"1/16"),/*#__PURE__*/React.createElement("option",{value:"1/32"},"1/32"),/*#__PURE__*/React.createElement("option",{value:"4"},"4")),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-6 bg-zinc-800 mx-1.5"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500 font-bold"},"Bars:"),/*#__PURE__*/React.createElement("input",{type:"number",min:"0",value:beginBar,onChange:e=>{const b=parseInt(e.target.value)||0;setBeginBar(b);const beatDuration=60/parseInt(bpm||120);const t=b*beatDuration*4;clearLocalSelection();setSelectionMode('global');setSelectionStart(t);setSelectionEnd(t+beatDuration*4);},className:"w-14 bg-black text-white text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500"},"-"),/*#__PURE__*/React.createElement("input",{type:"number",min:"0",value:endBar,onChange:e=>{const b=parseInt(e.target.value)||0;setEndBar(b);const beatDuration=60/parseInt(bpm||120);const t=b*beatDuration*4;setSelectionEnd(t+beatDuration*4);setNumberBar(b-beginBar+1);},className:"w-14 bg-black text-white text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500"},"#"),/*#__PURE__*/React.createElement("input",{type:"number",min:"1",value:numberBar,readOnly:true,className:"w-14 bg-black text-zinc-400 text-[14px] px-1 py-0.5 rounded border border-zinc-800 text-center font-mono"}),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-6 bg-zinc-800 mx-1.5"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500"},"Start:"),/*#__PURE__*/React.createElement("input",{type:"text",value:selLeft!==null?formatTime(selLeft):'',onChange:e=>{const parts=e.target.value.split(/[:.]/);if(parts.length===3){const secs=parseInt(parts[0])*60+parseInt(parts[1])+parseFloat('0.'+(parts[2]||'0'));clearLocalSelection();setSelectionMode('global');setSelectionStart(secs);}},className:"w-20 bg-black text-zinc-200 text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500"},"End:"),/*#__PURE__*/React.createElement("input",{type:"text",value:selRight!==null?formatTime(selRight):'',onChange:e=>{const parts=e.target.value.split(/[:.]/);if(parts.length===3){const secs=parseInt(parts[0])*60+parseInt(parts[1])+parseFloat('0.'+(parts[2]||'0'));setSelectionEnd(secs);}},className:"w-20 bg-black text-zinc-200 text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500"},"Len:"),/*#__PURE__*/React.createElement("input",{type:"text",value:selLeft!==null&&selRight!==null?formatTime(Math.abs(selRight-selLeft)):'',onChange:e=>{const parts=e.target.value.split(/[:.]/);if(parts.length===3&&selLeft!==null){const secs=parseInt(parts[0])*60+parseInt(parts[1])+parseFloat('0.'+(parts[2]||'0'));setSelectionEnd(selLeft+secs);}},className:"w-20 bg-black text-amber-300 text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono"}),/*#__PURE__*/React.createElement("div",{className:"flex-1"}),/*#__PURE__*/React.createElement("div",{className:"text-xs font-bold font-mono text-zinc-100"},formatTime(currentTime))),(()=>{const dockPanels={top:[],right:[],bottom:[],left:[]};const addPanel=(id,pos,visible)=>{if(visible)dockPanels[pos].push(id);};addPanel('export',panelPositions.export,showExportPanel);addPanel('ai',panelPositions.ai,showAIPanel);addPanel('python_tools',panelPositions.python_tools||'bottom',showPythonToolsPanel);addPanel('selection',panelPositions.selection,showSelectionPanel);addPanel('media_explorer','bottom',showMediaExplorer);addPanel('fx_rack',panelPositions.fx_rack||'bottom',showFxRack);addPanel('midi_events',panelPositions.midi_events||'bottom',showMidiEvents);const closePanel=id=>{if(id==='export')setShowExportPanel(false);else if(id==='ai')setShowAIPanel(false);else if(id==='python_tools')setShowPythonToolsPanel(false);else if(id==='selection')setShowSelectionPanel(false);else if(id==='media_explorer')setShowMediaExplorer(false);else if(id==='fx_rack')setShowFxRack(false);else if(id==='midi_events')setShowMidiEvents(false);};const renderPanelContent=panelId=>{const h=id=>e=>{startPanelDrag(id,e);};if(panelId==='export')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('export',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-zinc-200 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"save",className:"w-3.5 h-3.5 text-cyan-400"}))," Export"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('export'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Ngu\u1ed3n"),/*#__PURE__*/React.createElement("select",{value:exportSettings.source,onChange:e=>setExportSettings(p=>({...p,source:e.target.value})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"project"},"Project (Mix)"),/*#__PURE__*/React.createElement("option",{value:"track_mix"},"Track Selection"),/*#__PURE__*/React.createElement("option",{value:"active_clip"},"Active Clip"),/*#__PURE__*/React.createElement("option",{value:"clip_selection"},"Clip Selection"))),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"\u0110\u1ecbnh d\u1ea1ng"),/*#__PURE__*/React.createElement("select",{value:exportSettings.format,onChange:e=>setExportSettings(p=>({...p,format:e.target.value,sampleRate:e.target.value==='wav'?'44100':e.target.value==='mp3'?'44100':'44100',bitDepth:e.target.value==='wav'?'16':'16',quality:'44khz'})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"wav"},"WAV"),/*#__PURE__*/React.createElement("option",{value:"mp3"},"MP3"),/*#__PURE__*/React.createElement("option",{value:"ogg"},"OGG")))),exportSettings.format==='wav'?/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"SR (Hz)"),/*#__PURE__*/React.createElement("select",{value:exportSettings.sampleRate,onChange:e=>setExportSettings(p=>({...p,sampleRate:e.target.value})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"22500"},"22500"),/*#__PURE__*/React.createElement("option",{value:"44100"},"44100"))),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Bit"),/*#__PURE__*/React.createElement("select",{value:exportSettings.bitDepth,onChange:e=>setExportSettings(p=>({...p,bitDepth:e.target.value})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"8"},"8"),/*#__PURE__*/React.createElement("option",{value:"16"},"16"),/*#__PURE__*/React.createElement("option",{value:"24"},"24")))):/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Ch\u1ea5t l\u01b0\u1ee3ng"),/*#__PURE__*/React.createElement("select",{value:exportSettings.quality,onChange:e=>setExportSettings(p=>({...p,quality:e.target.value})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"44khz"},"44kHz"),/*#__PURE__*/React.createElement("option",{value:"lossless"},"Lossless"))),/*#__PURE__*/React.createElement("div",null)),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Kênh"),/*#__PURE__*/React.createElement("select",{value:exportSettings.channels,onChange:e=>setExportSettings(p=>({...p,channels:e.target.value})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"mono"},"Mono"),/*#__PURE__*/React.createElement("option",{value:"stereo"},"Stereo"))),/*#__PURE__*/React.createElement("div",null)),/*#__PURE__*/React.createElement("button",{onClick:triggerWavExport,disabled:isExporting,className:"w-full py-1 bg-cyan-700 hover:bg-cyan-600 text-zinc-100 font-bold rounded text-xs flex items-center justify-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"download-cloud",className:"w-3 h-3"})),isExporting?'...':'Export'));if(panelId==='ai')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1.5 flex-1 min-h-0"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('ai',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-zinc-200 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"cpu",className:"w-3.5 h-3.5 text-purple-400"}))," AI Copilot"),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("button",{onClick:()=>setAiPresetModalOpen(true),className:"text-zinc-600 hover:text-zinc-300 mr-0.5",title:"Preset Manager"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sliders",className:"w-3 h-3"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{setAiActionLog([]);showToast('Đã xoá nhật ký AI.','info');},className:"text-zinc-600 hover:text-zinc-300",title:"Clear log"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"trash-2",className:"w-3 h-3"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('ai'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"}))))),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1.5 w-full min-w-0 pb-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"cpu",className:"w-3 h-3 text-purple-400"})),/*#__PURE__*/React.createElement("select",{value:selectedProviderId,onChange:e=>setSelectedProviderId(e.target.value),className:"flex-1 min-w-0 max-w-full bg-[#141414] text-zinc-200 border border-zinc-700 rounded px-1 py-0.5 text-xs font-mono focus:outline-none focus:border-purple-600 truncate"},aiProviders.length===0?/*#__PURE__*/React.createElement("option",{value:""},"Chưa có provider"):aiProviders.map(p=>/*#__PURE__*/React.createElement("option",{key:p.id,value:p.id},p.name,p.is_active?'':' (inactive)')))),/*#__PURE__*/React.createElement("div",{className:"border-t border-zinc-800 pt-1 mt-1 shrink-0"},/*#__PURE__*/React.createElement("button",{onClick:()=>{if(window.DAWCommandDispatcher&&window.DAWCommandDispatcher.undo){const entry=window.DAWCommandDispatcher.undo();if(entry){setAiActionLog(prev=>[...prev,{type:'undo',text:`Undo: ${entry.name}`,time:Date.now()}]);showToast(`Undo AI: ${entry.name}`,'info');}}else{handleUndo();setAiActionLog(prev=>[...prev,{type:'undo',text:'Undo (Ctrl+Z)',time:Date.now()}]);}},className:"w-full text-[10px] text-amber-400 hover:text-amber-300 border border-amber-800 rounded py-0.5"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center justify-center gap-1"},/*#__PURE__*/React.createElement("i",{"data-lucide":"rotate-ccw",className:"w-3 h-3"}),"Undo"))),/*#__PURE__*/React.createElement("div",{className:"flex-1 min-h-0 flex flex-col overflow-hidden mt-1"},/*#__PURE__*/React.createElement("div",{className:"text-[10px] font-bold text-zinc-400 uppercase shrink-0 pb-0.5"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center gap-1"},/*#__PURE__*/React.createElement("i",{"data-lucide":"list",className:"w-3 h-3"})," Action Log")),/*#__PURE__*/React.createElement("div",{ref:actionLogContainerRef,className:"flex-1 overflow-y-auto no-scrollbar bg-[#0f0f0f] rounded border border-zinc-800 select-text"},aiActionLog.length===0?/*#__PURE__*/React.createElement("div",{className:"text-xs text-zinc-600 italic select-text"},"Chưa có hành động nào."):aiActionLog.map((entry,i)=>/*#__PURE__*/React.createElement("div",{key:i,className:`text-xs font-mono py-0.5 border-b border-zinc-900 last:border-0 ${entry.type==='error'?'text-red-400':entry.type==='status'?'text-zinc-400 italic':entry.type==='undo'?'text-amber-400':'text-zinc-300'}`},new Date(entry.time).toLocaleTimeString(),entry.text)))),/*#__PURE__*/React.createElement("div",{className:"border-t border-zinc-800 pt-1.5 mt-1 shrink-0"},/*#__PURE__*/React.createElement("div",{className:"text-xs font-bold text-zinc-400 uppercase mb-1 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"message-square",className:"w-3 h-3"}))," Copilot Prompt"),/*#__PURE__*/React.createElement("textarea",{value:aiPrompt,onChange:e=>setAiPrompt(e.target.value),placeholder:"Nhập lệnh điều khiển DAW... (VD: Tạo track mới tên Beat, đặt BPM 128)",className:"w-full bg-[#1e1e1e] text-zinc-200 p-1.5 rounded border border-zinc-700 focus:outline-none focus:border-purple-600 font-mono text-xs resize-none",rows:2,onKeyDown:e=>{if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();handleAISend();}else if(e.key==='ArrowUp'&&promptHistRef.current.length>0){e.preventDefault();const idx=promptHistIdx===-1?promptHistRef.current.length-1:Math.max(0,promptHistIdx-1);setPromptHistIdx(idx);setAiPrompt(promptHistRef.current[idx]);}else if(e.key==='ArrowDown'){e.preventDefault();if(promptHistIdx===-1)return;const idx=promptHistIdx+1;if(idx>=promptHistRef.current.length){setPromptHistIdx(-1);setAiPrompt('');}else{setPromptHistIdx(idx);setAiPrompt(promptHistRef.current[idx]);}}}})),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1 mt-1 shrink-0"},/*#__PURE__*/React.createElement("button",{onClick:handleAISend,disabled:aiProcessing,className:"flex-1 py-1 bg-purple-700 hover:bg-purple-600 text-white font-bold rounded text-xs border border-purple-500 flex items-center justify-center gap-1"},aiProcessing?'Đang suy luận...':/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"send",className:"w-3 h-3"}))," Gửi")),/*#__PURE__*/React.createElement("button",{onClick:()=>{setAiPrompt('');setAiActionLog([]);},className:"px-2 py-1 bg-zinc-800 hover:bg-zinc-700 text-zinc-400 rounded text-xs border border-zinc-700"},"Clear")),/*#__PURE__*/React.createElement("div",{className:"text-xs text-zinc-600 shrink-0"},"Enter để gửi nhanh"));if(panelId==='python_tools')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('python_tools',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-amber-300 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"wrench",className:"w-3.5 h-3.5 text-amber-400"}))," DSP Tools"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('python_tools'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"p-1.5 bg-[#141414] rounded border border-zinc-800 text-[10px] font-mono text-zinc-400 space-y-0.5 leading-relaxed"},dspSelectionStats?[/*#__PURE__*/React.createElement("div",{key:"track"},`Track: ${dspSelectionStats.trackName}`),/*#__PURE__*/React.createElement("div",{key:"range"},`Range: ${dspSelectionStats.timeRange}`),/*#__PURE__*/React.createElement("div",{key:"ch"},`Channels: ${dspSelectionStats.channels}`),/*#__PURE__*/React.createElement("div",{key:"peak"},`Peak Vol: ${dspSelectionStats.peakVolume}`)]:"Chưa chọn track"),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1 text-xs"},/*#__PURE__*/React.createElement("button",{onClick:()=>runPythonTool('normalize'),className:"py-1 bg-amber-950/80 hover:bg-amber-900 text-amber-300 border border-amber-800/80 rounded font-bold flex items-center justify-center gap-1"},"⚡ Peak Norm (0dB)"),/*#__PURE__*/React.createElement("button",{onClick:()=>runPythonTool('invert_phase'),className:"py-1 bg-zinc-800 hover:bg-zinc-700 text-zinc-200 border border-zinc-700 rounded font-bold flex items-center justify-center gap-1"},"🔄 Phase Invert"),/*#__PURE__*/React.createElement("button",{onClick:()=>runPythonTool('swap_channels'),className:"py-1 bg-zinc-800 hover:bg-zinc-700 text-zinc-200 border border-zinc-700 rounded font-bold flex items-center justify-center gap-1"},"🔀 Swap L/R"),/*#__PURE__*/React.createElement("button",{onClick:()=>runPythonTool('synth_wave'),className:"py-1 bg-teal-950/80 hover:bg-teal-900 text-teal-300 border border-teal-800/80 rounded font-bold flex items-center justify-center gap-1"},"🎹 Gen Synth Tone")));if(panelId==='selection')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('selection',e)},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500 font-bold uppercase flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"}))," Selection"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('selection'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-3 gap-1 bg-[#141414] p-1.5 rounded border border-zinc-800"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("span",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Start"),/*#__PURE__*/React.createElement("input",{type:"number",step:"0.01",value:selectionStats.start,onChange:e=>handleSelectionInputChange('start',e.target.value),className:"w-full bg-[#242424] text-amber-400 text-center font-mono text-xs rounded py-0.5 border border-zinc-700 focus:outline-none"})),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("span",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"End"),/*#__PURE__*/React.createElement("input",{type:"number",step:"0.01",value:selectionStats.end,onChange:e=>handleSelectionInputChange('end',e.target.value),className:"w-full bg-[#242424] text-amber-400 text-center font-mono text-xs rounded py-0.5 border border-zinc-700 focus:outline-none"})),/*#__PURE__*/React.createElement("div",{className:"flex flex-col justify-center"},/*#__PURE__*/React.createElement("span",{className:"text-[7px] text-zinc-500 font-bold uppercase"},"Len"),/*#__PURE__*/React.createElement("span",{className:"text-zinc-200 font-mono text-xs font-semibold mt-0.5"},selectionStats.length,"s"))),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-3 gap-1 bg-[#141414] p-1.5 rounded border border-zinc-800 mt-1"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("span",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Begin Bar"),/*#__PURE__*/React.createElement("input",{type:"number",min:"0",value:beginBar,onChange:e=>{const b=parseInt(e.target.value)||0;setBeginBar(b);const beatDuration=60/parseInt(bpm||120);const t=b*beatDuration*4;clearLocalSelection();setSelectionMode('global');setSelectionStart(t);setSelectionEnd(t+beatDuration*4);},className:"w-full bg-[#242424] text-white text-center font-mono text-xs rounded py-0.5 border border-zinc-700 focus:outline-none"})),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("span",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"End Bar"),/*#__PURE__*/React.createElement("input",{type:"number",min:"0",value:endBar,onChange:e=>{const b=parseInt(e.target.value)||0;setEndBar(b);const beatDuration=60/parseInt(bpm||120);const t=b*beatDuration*4;setSelectionEnd(t+beatDuration*4);setNumberBar(b-beginBar+1);},className:"w-full bg-[#242424] text-white text-center font-mono text-xs rounded py-0.5 border border-zinc-700 focus:outline-none"})),/*#__PURE__*/React.createElement("div",{className:"flex flex-col justify-center"},/*#__PURE__*/React.createElement("span",{className:"text-[7px] text-zinc-500 font-bold uppercase"},"# Bars"),/*#__PURE__*/React.createElement("span",{className:"text-zinc-200 font-mono text-xs font-semibold mt-0.5"},numberBar))));if(panelId==='media_explorer')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('media_explorer',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-emerald-300 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"folder-open",className:"w-3.5 h-3.5 text-emerald-400"}))," Media Explorer"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('media_explorer'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"flex-1 overflow-y-auto text-xs text-zinc-400 font-mono p-2"},"// Placeholder: Media files browser"));if(panelId==='fx_rack')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('fx_rack',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-rose-300 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sliders",className:"w-3.5 h-3.5 text-rose-400"}))," Plugin FX Rack"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('fx_rack'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"flex-1 text-xs text-zinc-500 italic flex items-center justify-center"},"No FX plugins loaded"));if(panelId==='midi_events')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('midi_events',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-sky-300 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"music",className:"w-3.5 h-3.5 text-sky-400"}))," MIDI Event List"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('midi_events'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"flex-1 text-xs text-zinc-500 italic flex items-center justify-center"},"No MIDI events selected"));return null;};const renderDock=(pos,title)=>{const panels=dockPanels[pos];if(panels.length===0)return null;const isSide=pos==='left'||pos==='right';const borderClass=pos==='left'?'border-r':pos==='right'?'border-l':pos==='top'?'border-b':'border-t';const bgClass='bg-[#1e1e1e]';const highlight=panelDragRef.current&&panelDropZone===pos;if(pos==='right')return/*#__PURE__*/React.createElement("div",{id:"right-sidebar",className:`${borderClass} ${bgClass} flex flex-col overflow-hidden select-none h-full`,style:{width:`${rightSidebarWidth}px`,minWidth:'200px',maxWidth:'600px',flexShrink:0}},/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col gap-2 p-2 overflow-hidden h-full"},panels.map((p,idx)=>/*#__PURE__*/React.createElement(React.Fragment,{key:p},/*#__PURE__*/React.createElement("div",{className:'flex flex-col flex-1 min-h-0 border border-zinc-700 rounded-lg bg-[#262626] shadow-sm p-3'},renderPanelContent(p)),idx/*#__PURE__*/React.createElement("div",{key:p,className:`${isSide?'w-full':'flex-none w-[320px]'} border border-zinc-700 rounded-lg bg-[#262626] shadow-sm p-2`},renderPanelContent(p))));};return/*#__PURE__*/React.createElement("div",{ref:workspaceRef,className:"flex-1 flex flex-col overflow-hidden select-none daw-bg relative"},panelDragRef.current&&panelDropZone&&/*#__PURE__*/React.createElement("div",{className:"absolute inset-0 z-50 pointer-events-none"},panelDropZone==='top'&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 left-0 right-0 h-1 bg-cyan-400 shadow-[0_0_8px_#06b6d4]"}),panelDropZone==='bottom'&&/*#__PURE__*/React.createElement("div",{className:"absolute bottom-0 left-0 right-0 h-1 bg-cyan-400 shadow-[0_0_8px_#06b6d4]"}),panelDropZone==='left'&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 left-0 w-1 bg-cyan-400 shadow-[0_0_8px_#06b6d4]"}),panelDropZone==='right'&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 right-0 w-1 bg-cyan-400 shadow-[0_0_8px_#06b6d4]"})),dragGhostPanel&&dragGhostPos&&/*#__PURE__*/React.createElement("div",{className:"fixed z-[100] pointer-events-none opacity-80 border border-cyan-500 rounded-lg bg-[#262626] shadow-2xl p-3 w-56",style:{left:dragGhostPos.x,top:dragGhostPos.y}},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2 text-xs text-zinc-200 font-bold"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"move",className:"w-3.5 h-3.5 text-cyan-400"})),dragGhostPanel==='export'?'Export Panel':dragGhostPanel==='ai'?'AI Panel':dragGhostPanel==='python_tools'?'Audio Processing Panel':'Selection Panel'),/*#__PURE__*/React.createElement("div",{className:"text-xs text-zinc-500 mt-1"},"Drop at edge to dock")),renderDock('top','Top'),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex overflow-hidden"},renderDock('left','Left'),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col overflow-hidden min-w-0"},/*#__PURE__*/React.createElement("div",{className:"flex-1 flex overflow-hidden"},activeTab==='main'||sessionTabs.some(s=>s.id===activeTab)?/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{ref:tcpContainerRef,onScroll:handleTCPScroll,className:"shrink-0 z-20 bg-[#262626] overflow-y-auto flex flex-col border-r border-zinc-900 no-scrollbar",style:{width:tcpWidth+'px',scrollbarWidth:'none',msOverflowStyle:'none'}},/*#__PURE__*/React.createElement("div",{className:"sticky top-0 z-50 flex items-center justify-between h-10 border-b border-zinc-900 bg-[#242424] px-2 shrink-0"},/*#__PURE__*/React.createElement("span",{className:"text-xs font-bold text-zinc-300 flex items-center gap-1.5"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sliders",className:"w-3.5 h-3.5 text-cyan-400"})),"TRACKS (",activeTracks.length,")"),/*#__PURE__*/React.createElement("button",{onClick:addNewTrack,className:"px-2.5 py-1 bg-cyan-600 hover:bg-cyan-500 text-white rounded text-xs font-semibold flex items-center gap-1 shadow transition"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus",className:"w-3 h-3"}))," Add Track")),/*#__PURE__*/React.createElement("div",{className:"sticky top-10 z-40 flex h-[40px] border-b border-purple-500/30 bg-[#1a1a2e] p-2 border-l-4 border-purple-500 shrink-0"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between w-full"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"text-xs font-bold text-purple-400 font-mono"},"TM"),/*#__PURE__*/React.createElement("span",{className:"text-xs font-semibold text-zinc-300"},"Tempo")),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("input",{type:"number",value:bpm,onChange:e=>setBpm(e.target.value),onBlur:()=>localStorage.setItem('studio_bpm',bpm),className:"w-12 bg-zinc-800 border border-zinc-700 rounded text-xs text-zinc-300 text-center font-mono focus:outline-none focus:border-purple-500",min:"40",max:"300"}),/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500"},"BPM")))),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col divide-y divide-[#141414] bg-[#262626]"},activeTracks.length===0?/*#__PURE__*/React.createElement("div",{className:"p-6 text-center text-zinc-400 flex flex-col items-center justify-center space-y-3"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus-circle",className:"w-8 h-8 text-cyan-400 opacity-80"})),/*#__PURE__*/React.createElement("p",{className:"text-xs font-medium"},"Chưa có Track nào trong dự án."),/*#__PURE__*/React.createElement("button",{onClick:addNewTrack,className:"px-3 py-1.5 bg-cyan-600 hover:bg-cyan-500 text-white rounded text-xs font-semibold flex items-center gap-1.5 shadow"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus-circle",className:"w-3.5 h-3.5"}))," Thêm Track Mới")):activeTracks.map((track,idx)=>{const isSelected=selectedTrackId===track.id;const autoHeight=track.height||(track.isArmed?164:140);return/*#__PURE__*/React.createElement("div",{key:track.id,style:{height:`${autoHeight}px`},className:`shrink-0 relative flex flex-col justify-between p-2.5 bg-[#1e1e1e] border-r border-zinc-900 cursor-pointer border-l-4 border-b border-[#141414] overflow-hidden ${isSelected?'border-cyan-500 bg-[#252525]':'border-transparent hover:bg-zinc-800/20'}`,onClick:()=>setSelectedTrackId(track.id)},/*#__PURE__*/React.createElement("div",{className:"flex items-start justify-between"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"text-xs font-bold text-zinc-500 font-mono"},(idx+1).toString().padStart(2,'0')),/*#__PURE__*/React.createElement("label",{onClick:e=>{e.stopPropagation();const el=e.currentTarget.querySelector('input');if(el)el.click();},className:"cursor-pointer"},/*#__PURE__*/React.createElement("input",{type:"color",value:track.color||'#0f766e',onChange:e=>{e.stopPropagation();updateTrackColor(track.id,e.target.value);},className:"w-0 h-0 opacity-0 absolute pointer-events-none"}),/*#__PURE__*/React.createElement("div",{className:"w-3 h-3 rounded-full border border-zinc-600 hover:scale-110 transition-transform",style:{backgroundColor:track.color}})),editingTrackName===track.id?/*#__PURE__*/React.createElement("input",{type:"text",value:editNameInput,autoFocus:true,onChange:e=>setEditNameInput(e.target.value),onBlur:()=>{updateTrackName(track.id,editNameInput||track.name);setEditingTrackName(null);},onKeyDown:e=>{if(e.key==='Enter'){updateTrackName(track.id,editNameInput||track.name);setEditingTrackName(null);}if(e.key==='Escape')setEditingTrackName(null);},onClick:e=>e.stopPropagation(),className:"text-xs font-semibold bg-black text-zinc-200 border border-cyan-500 rounded px-1 py-0 w-24 outline-none"}):/*#__PURE__*/React.createElement("span",{className:"text-xs font-semibold text-zinc-300 truncate max-w-[80px] cursor-text hover:text-cyan-300 transition-colors",title:"Click to rename",onClick:e=>{e.stopPropagation();setEditingTrackName(track.id);setEditNameInput(track.name);}},track.name)),/*#__PURE__*/React.createElement("div",{className:"flex flex-wrap gap-0.5 max-w-[100px] mb-0.5"},(track.clips&&track.clips.length>0?track.clips:track.buffer?[{id:'default',name:track.name,startTime:track.startTime}]:[]).slice(0,3).map(c=>/*#__PURE__*/React.createElement("span",{key:c.id,className:"text-[9px] font-mono text-zinc-500 bg-zinc-800/60 rounded px-0.5 truncate max-w-[90px] cursor-pointer hover:text-cyan-400 hover:bg-zinc-700",title:c.name||track.name,onClick:e=>{e.stopPropagation();setSelectedTrackId(track.id);clearLocalSelection();setSelectionMode('global');const start=c.startTime||0;const end=start+(c.buffer?c.buffer.duration:2);setSelectionStart(start);setSelectionEnd(end);showToast(`Selected: ${c.name||track.name}`,'info');}},c.name||track.name),editingClipName&&editingClipName.trackId===track.id&&editingClipName.clipId===c.id?/*#__PURE__*/React.createElement("input",{type:"text",value:editNameInput,autoFocus:true,onChange:e=>setEditNameInput(e.target.value),onBlur:()=>{if(editNameInput.trim())updateClipName(track.id,c.id,editNameInput.trim());setEditingClipName(null);},onKeyDown:e=>{if(e.key==='Enter'){if(editNameInput.trim())updateClipName(track.id,c.id,editNameInput.trim());setEditingClipName(null);}if(e.key==='Escape')setEditingClipName(null);},onClick:e=>e.stopPropagation(),className:"w-20 text-[9px] font-mono bg-black text-cyan-300 border border-cyan-500 rounded px-0.5 py-0 outline-none"}):/*#__PURE__*/React.createElement("button",{className:"text-[9px] text-zinc-600 hover:text-cyan-400 ml-0.5 shrink-0",title:"Sửa tên clip",onClick:e=>{e.stopPropagation();setEditingClipName({trackId:track.id,clipId:c.id});setEditNameInput(c.name||track.name);}},/*#__PURE__*/React.createElement("i",{"data-lucide":"pencil",className:"w-2.5 h-2.5"})))),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackMute(track.id);},title:"Mute",className:`px-1.5 py-0.5 text-[10px] rounded font-mono font-bold border transition flex items-center gap-0.5 ${track.muted?'bg-red-950 text-red-400 border-red-700':'bg-zinc-800 text-zinc-400 border-transparent hover:text-zinc-200'}`},/*#__PURE__*/React.createElement("i",{"data-lucide":track.muted?"volume-x":"volume-2",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackSoloEvaluate(track.id);},title:"Solo",className:`px-1.5 py-0.5 text-[10px] rounded font-mono font-bold border transition flex items-center gap-0.5 ${soloedTrackId===track.id||track.solo?'bg-amber-950 text-amber-400 border-amber-600':'bg-zinc-800 text-zinc-400 border-transparent hover:text-zinc-200'}`},/*#__PURE__*/React.createElement("i",{"data-lucide":soloedTrackId===track.id||track.solo?"headphones":"headphone-off",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackArm(track.id);},title:"ARM (Record)",className:`px-1.5 py-0.5 text-[10px] rounded font-mono font-bold border transition flex items-center gap-0.5 ${track.isArmed?'bg-red-600 text-white border-red-500 hover:bg-red-500':'bg-zinc-800 text-zinc-400 border-transparent hover:text-zinc-200'}`},/*#__PURE__*/React.createElement("i",{"data-lucide":"circle",className:`w-2.5 h-2.5 ${track.isArmed?'fill-white':''}`})),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();const btn=e.currentTarget;setInstrumentDropdownTrackId(prev=>prev===track.id?null:track.id);setInstrumentDropdownBtnRect(btn.getBoundingClientRect());setInstrumentSearchQuery('');},title:track.instrumentName||track.instrumentId||"Synth",className:`px-1.5 py-0.5 text-[10px] rounded font-mono font-bold border transition flex items-center gap-0.5 max-w-[60px] ${track.instrumentId?'bg-violet-900 text-violet-300 border-violet-700':'bg-zinc-800 text-zinc-500 border-transparent hover:text-zinc-300'}`},/*#__PURE__*/React.createElement("i",{"data-lucide":"music",className:"w-3 h-3 shrink-0"}),/*#__PURE__*/React.createElement("span",{className:"truncate text-[9px]"},track.instrumentName||track.instrumentId||(instrumentDropdownTrackId===track.id?'':'Synth')),/*#__PURE__*/React.createElement("i",{"data-lucide":"chevron-down",className:"w-2.5 h-2.5 shrink-0"})),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackMonitor(track.id);},title:"Input Monitor",className:`px-1.5 py-0.5 text-[10px] rounded font-mono font-bold border transition flex items-center gap-0.5 ${track.monitoringEnabled?'bg-amber-600 text-white border-amber-500 hover:bg-amber-500':'bg-zinc-800 text-zinc-500 border-transparent hover:text-zinc-305'}`},/*#__PURE__*/React.createElement("i",{"data-lucide":track.monitoringEnabled?"mic":"mic-off",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();deleteTrack(track.id);},className:"p-0.5 rounded text-red-500 hover:bg-red-950/40 hover:text-red-400 transition"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"trash-2",className:"w-3 h-3"}))))),/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-0.5 text-xs",onClick:e=>e.stopPropagation()},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"w-8 text-right text-zinc-500 text-xs"},"Vol:"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-50",max:"7",step:"0.5",value:track.volumeDb??0,onChange:e=>updateTrackVolumeDb(track.id,parseFloat(e.target.value)),className:"flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-cyan-500",style:{height:'4px'}}),/*#__PURE__*/React.createElement("span",{className:"w-12 text-right font-mono text-zinc-300 text-xs"},track.volumeDb??0,"dB")),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"w-8 text-right text-zinc-500 text-xs"},"Pan:"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-100",max:"100",step:"1",value:track.pan??0,onChange:e=>updateTrackPan(track.id,parseInt(e.target.value)),className:"flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-purple-500",style:{height:'4px'}}),/*#__PURE__*/React.createElement("span",{className:"w-12 text-right font-mono text-zinc-300 text-xs"},track.pan>0?'R'+track.pan:track.pan<0?'L'+Math.abs(track.pan):'C')),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1 mt-0.5"},/*#__PURE__*/React.createElement("span",{className:"w-8 text-right text-zinc-500 text-[10px]"},"In:"),/*#__PURE__*/React.createElement("select",{value:`${track.inputSource?.deviceType||'NONE'}:${track.inputSource?.deviceId||''}`,onChange:e=>{const val=e.target.value;const parts=val.split(':');const type=parts[0];const id=parts.slice(1).join(':');updateTrackInputSource(track.id,type,id);},className:"flex-1 bg-[#18181b] text-zinc-300 text-[10px] rounded border border-zinc-700 focus:outline-none py-0.5 px-1 truncate max-w-[120px]"},/*#__PURE__*/React.createElement("option",{value:"NONE:"},"No Input"),/*#__PURE__*/React.createElement("optgroup",{label:"Microphones"},audioDevices.map(d=>/*#__PURE__*/React.createElement("option",{key:d.deviceId,value:`MICROPHONE:${d.deviceId}`},d.label||`Microphone ${d.deviceId.slice(0,5)}`))),/*#__PURE__*/React.createElement("optgroup",{label:"MIDI Keyboards"},/*#__PURE__*/React.createElement("option",{value:"MIDI_KEYBOARD:ALL"},"Any MIDI Keyboard"),midiDevices.map(d=>/*#__PURE__*/React.createElement("option",{key:d.id,value:`MIDI_KEYBOARD:${d.id}`},d.name||`MIDI Input ${d.id.slice(0,5)}`)))),track.isArmed&&lastMidiNote&&(lastMidiNote.length===0||Date.now()-lastMidiNote.time<3000)&&/*#__PURE__*/React.createElement("span",{className:"text-[9px] font-mono text-emerald-400 ml-0.5 truncate max-w-[60px] shrink-0",title:"MIDI Note:velocity:length"},`${midiPitchToName(lastMidiNote.pitch)}:${lastMidiNote.velocity}:${lastMidiNote.length>0?lastMidiNote.length.toFixed(2)+'s':'...'}`)),track.isArmed&&/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1 mt-0.5"},/*#__PURE__*/React.createElement("span",{className:"w-8 text-right text-zinc-500 text-[9px]"},"VU:"),/*#__PURE__*/React.createElement("canvas",{ref:el=>{if(el)trackVuRefs.current[track.id]=el;else delete trackVuRefs.current[track.id];},width:100,height:4,className:"flex-1 bg-[#18181b] rounded h-1"}))),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1.5 mt-1",onClick:e=>e.stopPropagation()},/*#__PURE__*/React.createElement("input",{type:"file",id:`upload-${track.id}`,accept:"audio/*",className:"hidden",onChange:e=>loadFileOnTrack(track.id,e.target.files[0])}),/*#__PURE__*/React.createElement("label",{htmlFor:`upload-${track.id}`,className:"px-2.5 py-1 bg-zinc-800 hover:bg-zinc-700 text-zinc-300 rounded text-xs flex items-center gap-1 cursor-pointer border border-zinc-700 font-medium"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"upload",className:"w-3 h-3"}))," File"),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();setFxSelectorTrackId(track.id);},className:"px-2.5 py-1 bg-zinc-800 hover:bg-zinc-700 text-purple-400 border border-purple-900 rounded text-xs font-bold flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"wand-2",className:"w-3 h-3"}))," FX: ",/*#__PURE__*/React.createElement("span",{className:"text-zinc-500 font-normal"},track.fxType||"None")),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();const btn=e.currentTarget;setInstrumentDropdownTrackId(prev=>prev===track.id?null:track.id);setInstrumentDropdownBtnRect(btn.getBoundingClientRect());setInstrumentSearchQuery('');},className:"px-2.5 py-1 bg-zinc-800 hover:bg-zinc-700 text-amber-400 border border-amber-800 rounded text-xs font-bold flex items-center gap-1 max-w-[120px]"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"music",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"truncate text-[10px]"},track.instrumentName||track.instrumentId||"Synth"),/*#__PURE__*/React.createElement("i",{"data-lucide":"chevron-down",className:"w-3 h-3 shrink-0"}))),/*#__PURE__*/React.createElement("div",{onMouseDown:e=>handleTrackResizeMouseDown(e,track.id),className:"absolute bottom-0 left-0 right-0 h-1 cursor-ns-resize z-30 hover:bg-cyan-500/50 transition-colors",onClick:e=>e.stopPropagation()}));})),/*#__PURE__*/React.createElement("div",{className:"h-[48px] border-r border-zinc-900 bg-[#1e1e1e]/50 shrink-0"})),/*#__PURE__*/React.createElement("div",{className:"w-1 cursor-ew-resize hover:bg-cyan-500/50 active:bg-cyan-400 transition-colors shrink-0 z-10",onMouseDown:startTcpResize}),/*#__PURE__*/React.createElement("div",{ref:handleTimelineWrapperRef,onScroll:handleTimelineScroll,className:"flex-1 relative z-10 overflow-x-auto overflow-y-auto min-w-0"},/*#__PURE__*/React.createElement("div",{style:{width:`${timelineWidth}px`},className:"relative flex flex-col min-h-full"},/*#__PURE__*/React.createElement(TimelineRuler,{bpm:parseInt(bpm)||120,zoom:zoom,timelineWidth:timelineWidth,viewportWidth:viewportWidth,onPlayheadSet:handlePlayheadSet,snapValue:snapValue,onRulerMouseDown:handleRulerMouseDown,scrollLeft:scrollLeft,canvasRedrawCount:canvasRedrawCount}),/*#__PURE__*/React.createElement(TempoTrackLane,{bpm:parseInt(bpm)||120,zoom:zoom,timelineWidth:timelineWidth,viewportWidth:viewportWidth,onPlayheadSet:handlePlayheadSet,snapValue:snapValue,onRulerMouseDown:handleRulerMouseDown,scrollLeft:scrollLeft,canvasRedrawCount:canvasRedrawCount}),selectionMode==='global'&&selLeft!==null&&selRight!==null&&selRight>selLeft&&/*#__PURE__*/React.createElement("div",{className:"absolute inset-0 pointer-events-none z-20",style:{left:`${selLeft*zoom}px`,width:`${(selRight-selLeft)*zoom}px`,top:'80px'}},/*#__PURE__*/React.createElement("div",{className:"w-full h-full bg-amber-500/10",style:{borderLeft:'1px solid #f59e0b',borderRight:'1px solid #f59e0b'}})),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col divide-y divide-[#141414] relative bg-[#111111] min-h-full"},activeTracks.map((track,idx)=>{const isSelected=selectedTrackId===track.id;const autoHeight=track.height||(track.isArmed?164:140);return/*#__PURE__*/React.createElement("div",{key:track.id,style:{height:`${autoHeight}px`},className:`shrink-0 relative border-b border-[#141414] hover:bg-zinc-850/5 transition-colors ${isSelected?'bg-zinc-800/10':''}`,onDragOver:e=>e.preventDefault(),onDrop:e=>{e.preventDefault();if(e.dataTransfer.files[0])loadFileOnTrack(track.id,e.dataTransfer.files[0]);},onMouseEnter:()=>setHoveredTrackId(track.id)},/*#__PURE__*/React.createElement(WaveformLane,{track:track,zoom:zoom,timelineWidth:timelineWidth,viewportWidth:viewportWidth,scrollLeft:scrollLeft,onSelectRange:handleSelectRange,onPlayheadSet:handlePlayheadSet,isSelected:isSelected,onSelectTrack:setSelectedTrackId,markers:track.markers,onTrackLaneMouseDown:handleTrackLaneMouseDown,onContextMenu:handleContextMenu,onClipDragStart:handleClipDragStart,onClipStretchStart:handleClipStretchStart,onSectionItemDragStart:handleSectionItemDragStart,onSectionItemResizeStart:handleSectionItemResizeStart,onSelectionEdgeDragStart:handleSelectionEdgeDragStart,setSelectedClipId:setSelectedClipId,selectedClipId:selectedClipId,activeTool:activeTool,onSplitTrackAtTime:handleSplitTrackAtTime,onEditClipInSubTab:handleEditClipInSubTab,onEditSectionInTab:handleEditSectionInTab,onEditMidiInTab:handleEditMidiInTab,snapValue:snapValue,bpm:bpm,selectionMode:selectionMode,localSelectionTrackId:localSelectionTrackId,localSelectionStart:localSelectionStart,currentTime:currentTime,getLocalAnchor:()=>localSelectionAnchorRef.current,onClearLocalSelection:clearLocalSelection,onSetSelectionMode:setSelectionMode,onSetSelectionStart:setSelectionStart,onSetSelectionEnd:setSelectionEnd,onSetCurrentTime:setCurrentTime,onSetLocalSelectionTrackId:setLocalSelectionTrackId,onSetLocalSelectionStart:setLocalSelectionStart,onSetLocalSelectionEnd:setLocalSelectionEnd,localSelLeft:localSelectionStart!==null&&localSelectionEnd!==null?Math.min(localSelectionStart,localSelectionEnd):null,localSelRight:localSelectionStart!==null&&localSelectionEnd!==null?Math.max(localSelectionStart,localSelectionEnd):null,scrollLeft:scrollLeft,recordingState:recordingState,recTempMidiNotes:recTempMidiNotes,recTempAudioBuffer:recTempAudioBuffer,recStartTimelineTime:recStartTimelineTime,canvasRedrawCount:canvasRedrawCount}),selectionMode==='local'&&localSelectionTrackId===track.id&&localSelectionStart!==null&&localSelectionEnd!==null&&Math.abs(localSelectionEnd-localSelectionStart)>0&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 border-l border-r border-amber-400 bg-amber-500/20 z-20 pointer-events-none",style:{left:`${Math.min(localSelectionStart,localSelectionEnd)*zoom}px`,width:`${Math.abs(localSelectionEnd-localSelectionStart)*zoom}px`}},/*#__PURE__*/React.createElement("div",{className:"absolute -left-[1px] top-0 bottom-0 w-[2px] bg-amber-400 z-30 pointer-events-auto cursor-ew-resize",onMouseDown:e=>handleHandleDragStart(e,'left')}),/*#__PURE__*/React.createElement("div",{className:"absolute -right-[1px] top-0 bottom-0 w-[2px] bg-amber-400 z-30 pointer-events-auto cursor-ew-resize",onMouseDown:e=>handleHandleDragStart(e,'right')})),track.buffer&&/*#__PURE__*/React.createElement("div",{className:"absolute right-2 top-2 flex items-center gap-1 z-10 opacity-70 hover:opacity-100"},/*#__PURE__*/React.createElement("button",{onClick:()=>handleSplitTrack(track.id),className:"px-1.5 py-0.5 bg-zinc-900/95 text-zinc-300 rounded text-xs flex items-center gap-1 border border-zinc-700/50"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-2.5 h-2.5 text-cyan-400"}))," Cắt")),/*#__PURE__*/React.createElement("div",{onMouseDown:e=>handleTrackResizeMouseDown(e,track.id),className:"absolute bottom-0 left-0 right-0 h-1 cursor-ns-resize z-30 hover:bg-cyan-500/50 transition-colors",onClick:e=>e.stopPropagation()}));}),/*#__PURE__*/React.createElement("div",{className:"h-[48px] flex items-center justify-center text-xs text-zinc-500 hover:bg-zinc-900/20 cursor-pointer select-none border-t border-dashed border-zinc-800",onMouseEnter:()=>{if(draggedClipRef.current||draggedSectionItemRef.current){setHoveredTrackId(addNewTrack());}},onClick:addNewTrack},/*#__PURE__*/React.createElement("span",{className:"flex items-center gap-1 text-zinc-400"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus",className:"w-3.5 h-3.5"}))," Kéo clip xuống hoặc Click tạo Track")),selectionMode==='global'&&selLeft!==null&&selRight!==null&&selRight>selLeft&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 border-l border-r border-amber-500 bg-amber-500/10 z-20 selection-interactive-box cursor-grab active:cursor-grabbing",style:{left:`${selLeft*zoom}px`,width:`${(selRight-selLeft)*zoom}px`},onMouseDown:handleSelectionBodyDragStart},/*#__PURE__*/React.createElement("div",{className:"absolute -left-[1px] top-0 bottom-0 w-[1px] bg-amber-500 hover:bg-amber-400 cursor-ew-resize z-30",onMouseDown:e=>handleHandleDragStart(e,'left')}),/*#__PURE__*/React.createElement("div",{className:"absolute -right-[1px] top-0 bottom-0 w-[1px] bg-amber-500 hover:bg-amber-400 cursor-ew-resize z-30",onMouseDown:e=>handleHandleDragStart(e,'right')})),/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 w-[2px] bg-[#ef4444] z-20 pointer-events-none",style:{left:`${playheadLeftPos}px`}},/*#__PURE__*/React.createElement("div",{className:"w-3 h-3 bg-[#ef4444] rotate-45 transform -translate-x-1/2 -translate-y-1/2 absolute top-0"})))))):(()=>{const st=subTabs.find(s=>s.id===activeTab);if(!st)return null;if(st.type==='PIANO_ROLL'){return/*#__PURE__*/React.createElement(PianoRollTabEditor,{st:st,zoom:zoom,bpm:bpm,viewportWidth:viewportWidth,onClose:()=>closeSubTab(st.id),onUpdateNotes:handleUpdateMidiNotes,onSaveNotes:handleSaveMidiNotes,setSubTabs:setSubTabs,onPlayPause:handlePlayPause,onStop:stopAllPlayback,isPlaying:isPlaying,playPreviewNote:playMidiPreviewNote,showToast:showToast,midiDevices:midiDevices,recordingState:recordingState,recTempMidiNotes:recTempMidiNotes,onRecord:handleRecordClick,selectedMidiInputId:selectedMidiInputId,onMidiInputSelect:handleMidiInputSelect,activeMidiPitches:activeMidiPitches,onInstrumentSelect:trackId=>{openInstrumentSelector(trackId);},onRescheduleMidi:()=>{const playingSub=subTabs.find(s=>s.id===activeTab&&s.type==='PIANO_ROLL'&&s.isPlaying);if(playingSub){const offset=playingSub.currentTime||0;window.SonicSF.stopAll();setTimeout(()=>{const ctx=getAudioContext();startOffsetTimeRef.current=offset;startAudioTimeRef.current=ctx.currentTime;startBufferOffsetRef.current=offset*(playingSub.speed||1.0);schedulePianoRollMidi(playingSub,offset);},20);}}});}const subTrack=tracks.find(t=>t.id===st.trackId);const vTrack=subTrack?{...subTrack,buffer:st.buffer,isSubTab:true}:null;const subTabDuration=st.type==='PIANO_ROLL'?(()=>{const notes=st.notes||[];const beatSec=60.0/(parseFloat(bpm)||120);let maxEnd=0;notes.forEach(n=>{const end=(n.start_beat||0)+(n.duration_beats||1);if(end>maxEnd)maxEnd=end;});return maxEnd*beatSec+1.0;})():st.buffer&&'duration'in st.buffer?st.buffer.duration:4.0;const subTabTimelineWidth=Math.max(zoom*subTabDuration,viewportWidth);return/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{className:"shrink-0 z-30 bg-[#262626] overflow-y-scroll no-scrollbar flex flex-col border-r border-zinc-900",style:{width:tcpWidth+'px',scrollbarWidth:'none',msOverflowStyle:'none'}},/*#__PURE__*/React.createElement("div",{className:"sticky top-0 z-50 flex items-center h-10 border-b border-zinc-900 bg-[#242424] px-2 justify-between shrink-0"},/*#__PURE__*/React.createElement("span",{className:"text-xs font-bold text-zinc-500 uppercase"},"Sub-Tab"),/*#__PURE__*/React.createElement("button",{onClick:()=>closeSubTab(st.id),className:"px-1.5 py-0.5 text-xs bg-zinc-800 hover:bg-zinc-700 text-zinc-400 rounded border border-zinc-700 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"}))," Close")),vTrack?/*#__PURE__*/React.createElement("div",{key:vTrack.id,className:"flex-1 flex flex-col p-2.5 bg-[#1e1e1e] border-r border-zinc-900 border-l-4 border-l-cyan-500"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between mb-2"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2"},/*#__PURE__*/React.createElement("label",{onClick:e=>{e.stopPropagation();const el=e.currentTarget.querySelector('input');if(el)el.click();},className:"cursor-pointer"},/*#__PURE__*/React.createElement("input",{type:"color",value:vTrack.color||'#0f766e',onChange:e=>{e.stopPropagation();updateTrackColor(vTrack.id,e.target.value);},className:"w-0 h-0 opacity-0 absolute pointer-events-none"}),/*#__PURE__*/React.createElement("div",{className:"w-3 h-3 rounded-full border border-zinc-600 hover:scale-110 transition-transform",style:{backgroundColor:vTrack.color}})),editingTrackName===vTrack.id?/*#__PURE__*/React.createElement("input",{type:"text",value:editNameInput,autoFocus:true,onChange:e=>setEditNameInput(e.target.value),onBlur:()=>{updateTrackName(vTrack.id,editNameInput||vTrack.name);setEditingTrackName(null);},onKeyDown:e=>{if(e.key==='Enter'){updateTrackName(vTrack.id,editNameInput||vTrack.name);setEditingTrackName(null);}if(e.key==='Escape')setEditingTrackName(null);},onClick:e=>e.stopPropagation(),className:"text-xs font-semibold bg-black text-zinc-200 border border-cyan-500 rounded px-1 py-0 w-24 outline-none"}):/*#__PURE__*/React.createElement("span",{className:"text-xs font-semibold text-zinc-300 truncate max-w-[80px] cursor-text hover:text-cyan-300 transition-colors",title:"Click to rename",onClick:e=>{e.stopPropagation();setEditingTrackName(vTrack.id);setEditNameInput(vTrack.name);}},vTrack.name)),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackMute(vTrack.id);},className:`px-1.5 py-0.5 text-xs rounded font-mono font-bold border ${vTrack.muted?'bg-red-950 text-red-400 border-red-700':'bg-zinc-800 text-zinc-400 border-transparent hover:text-zinc-200'}`},"M"),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackSoloEvaluate(vTrack.id);},className:`px-1.5 py-0.5 text-xs rounded font-mono font-bold border ${soloedTrackId===vTrack.id||vTrack.solo?'bg-amber-950 text-amber-400 border-amber-600':'bg-zinc-800 text-zinc-400 border-transparent hover:text-zinc-200'}`},"S"))),/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-2.5 text-[14px] mb-3"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"w-10 text-right text-zinc-500 text-[14px]"},"Vol:"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-50",max:"7",step:"0.5",id:`tcp-vol-${st.id}`,value:vTrack.volumeDb??0,onChange:e=>updateTrackVolumeDb(vTrack.id,parseFloat(e.target.value)),className:"flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-cyan-500",style:{height:'4px'}}),/*#__PURE__*/React.createElement("span",{className:"w-16 text-right font-mono text-zinc-300 text-[14px]",id:`tcp-vol-label-${st.id}`},vTrack.volumeDb??0,"dB")),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"w-10 text-right text-zinc-500 text-[14px]"},"Pan:"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-100",max:"100",step:"1",id:`tcp-pan-${st.id}`,value:vTrack.pan??0,onChange:e=>updateTrackPan(vTrack.id,parseInt(e.target.value)),className:"flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-purple-500",style:{height:'4px'}}),/*#__PURE__*/React.createElement("span",{className:"w-16 text-right font-mono text-zinc-300 text-[14px]",id:`tcp-pan-label-detailed-${st.id}`},vTrack.pan>0?'R'+vTrack.pan:vTrack.pan<0?'L'+Math.abs(vTrack.pan):'C')),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1.5 text-[14px]"},/*#__PURE__*/React.createElement("button",{onClick:()=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,isLooping:!s.isLooping}:s)),className:`px-2 py-0.5 text-[14px] rounded border font-bold ${st.isLooping?'bg-amber-700 text-white border-amber-500':'bg-zinc-800 text-zinc-400 border-zinc-700'}`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"repeat",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>updateSubTabEffects(st.id,{reverse:!(st.effects||{}).reverse}),className:`px-2 py-0.5 rounded border text-[14px] font-bold ${(st.effects||{}).reverse?'bg-zinc-600 text-white border-zinc-500':'bg-zinc-800 text-zinc-400 border-zinc-700'} flex items-center justify-center`,title:"Reverse"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"arrow-left-right",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("span",{className:"w-10 text-right text-zinc-500 text-[14px]"},"Loop:"),/*#__PURE__*/React.createElement("input",{type:"number",min:"0",max:"999",value:st.loopCount||0,onChange:e=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,loopCount:Math.max(0,parseInt(e.target.value)||0)}:s)),className:"w-12 bg-black text-amber-300 text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono",title:"Loop count"}))),/*#__PURE__*/React.createElement("div",{className:"flex gap-1 justify-between my-2.5"},/*#__PURE__*/React.createElement("div",{className:"flex flex-col items-center bg-zinc-900/60 p-1.5 rounded border border-zinc-800 flex-1"},/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-bold text-zinc-400 uppercase tracking-tighter",title:"Normalize"},"Norm"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-12",max:"0",step:"0.1",value:subTabNormVal,onChange:e=>setSubTabNormVal(parseFloat(e.target.value)),style:{writingMode:'vertical-lr',direction:'rtl',height:'120px',width:'20px',accentColor:'#a1a1aa'},className:"my-2 cursor-pointer"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-mono text-zinc-300 font-bold"},subTabNormVal,"dB"),/*#__PURE__*/React.createElement("button",{onClick:()=>applySubTabEffect(st.id,'normalize',subTabNormVal),className:"mt-1.5 px-1 py-1 bg-zinc-700 hover:bg-zinc-600 text-zinc-100 rounded text-[14px] font-bold w-full uppercase border border-zinc-650"},"Apply")),/*#__PURE__*/React.createElement("div",{className:"flex flex-col items-center bg-zinc-900/60 p-1.5 rounded border border-zinc-800 flex-1"},/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-bold text-zinc-400 uppercase tracking-tighter",title:"Pitch Shift"},"Pitch"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-12",max:"12",step:"0.5",value:subTabPitchVal,onChange:e=>setSubTabPitchVal(parseFloat(e.target.value)),style:{writingMode:'vertical-lr',direction:'rtl',height:'120px',width:'20px',accentColor:'#a1a1aa'},className:"my-2 cursor-pointer"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-mono text-zinc-300 font-bold"},subTabPitchVal>0?'+':'',subTabPitchVal,"st"),/*#__PURE__*/React.createElement("button",{onClick:()=>applySubTabEffect(st.id,'pitch',subTabPitchVal),className:"mt-1.5 px-1 py-1 bg-zinc-700 hover:bg-zinc-600 text-zinc-100 rounded text-[14px] font-bold w-full uppercase border border-zinc-650"},"Apply")),/*#__PURE__*/React.createElement("div",{className:"flex flex-col items-center bg-zinc-900/60 p-1.5 rounded border border-zinc-800 flex-1"},/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-bold text-zinc-400 uppercase tracking-tighter",title:"Gain Multiplier"},"Gain"),/*#__PURE__*/React.createElement("input",{type:"range",min:"0",max:"150",step:"1",value:subTabGainVal,onChange:e=>setSubTabGainVal(parseInt(e.target.value)),style:{writingMode:'vertical-lr',direction:'rtl',height:'120px',width:'20px',accentColor:'#a1a1aa'},className:"my-2 cursor-pointer"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-mono text-zinc-300 font-bold"},subTabGainVal,"%"),/*#__PURE__*/React.createElement("button",{onClick:()=>applySubTabEffect(st.id,'gain',subTabGainVal),className:"mt-1.5 px-1 py-1 bg-zinc-700 hover:bg-zinc-600 text-zinc-100 rounded text-[14px] font-bold w-full uppercase border border-zinc-650"},"Apply"))),/*#__PURE__*/React.createElement("div",{className:"flex-1"}),/*#__PURE__*/React.createElement("div",{className:"mt-auto pt-2.5 border-t border-zinc-800"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between text-[14px] text-zinc-500 mb-1 font-semibold uppercase"},/*#__PURE__*/React.createElement("span",null,"Duration:"),/*#__PURE__*/React.createElement("span",{className:"font-mono text-zinc-300"},st.buffer?formatTime(subTabDuration):'0s')),/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between text-[14px] text-zinc-500 mb-2.5 font-semibold uppercase"},/*#__PURE__*/React.createElement("span",null,"SR:"),/*#__PURE__*/React.createElement("span",{className:"font-mono text-zinc-300"},st.buffer?st.buffer.sampleRate:0," Hz")),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1 mb-2"},/*#__PURE__*/React.createElement("button",{onClick:async e=>{subTabAiTrackIdRef.current=st.trackId;handleAIScan();},disabled:analysisState.isRunning,className:"py-1 bg-purple-900 hover:bg-purple-800 text-purple-100 font-bold rounded text-xs border border-purple-700 flex items-center justify-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"map-pin",className:"w-3 h-3"}))," Scan"),/*#__PURE__*/React.createElement("button",{onClick:async e=>{subTabAiTrackIdRef.current=st.trackId;handleAICutToNewTrack();},disabled:analysisState.isRunning,className:"py-1 bg-fuchsia-800 hover:bg-fuchsia-700 text-white font-bold rounded text-xs flex items-center justify-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-3 h-3"}))," Cut"),/*#__PURE__*/React.createElement("button",{onClick:async e=>{subTabAiTrackIdRef.current=st.trackId;if(st.buffer){setSelectionRangeOnBuffer(st.buffer,st.selectionStart||0,st.selectionEnd||st.buffer.duration);}handleAIAnalysicLoop();},disabled:analysisState.isRunning,className:"py-1 bg-violet-800 hover:bg-violet-700 text-violet-100 font-bold rounded text-xs border border-violet-600 flex items-center justify-center gap-1 col-span-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sparkles",className:"w-3 h-3"}))," AI Analysic Loop")),/*#__PURE__*/React.createElement("button",{onClick:()=>exportSubTabBuffer(st.id),className:"w-full py-1.5 mb-1.5 bg-blue-700 hover:bg-blue-600 text-white font-bold rounded text-[14px] flex items-center justify-center gap-1 transition"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"download",className:"w-4 h-4"}))," Export"),/*#__PURE__*/React.createElement("button",{onClick:()=>applySubTab(st.id),className:"w-full py-1.5 bg-emerald-700 hover:bg-emerald-600 text-white font-bold rounded text-[14px] flex items-center justify-center gap-1 transition"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"save",className:"w-4 h-4"}))," Save"))):/*#__PURE__*/React.createElement("div",{className:"flex-1 flex items-center justify-center text-xs text-zinc-500"},"Track not found")),/*#__PURE__*/React.createElement("div",{className:"w-1 cursor-ew-resize hover:bg-cyan-500/50 active:bg-cyan-400 transition-colors shrink-0 z-10",onMouseDown:startTcpResize}),/*#__PURE__*/React.createElement("div",{ref:handleTimelineWrapperRef,className:"flex-1 relative z-10 overflow-x-auto overflow-y-auto min-w-0"},/*#__PURE__*/React.createElement("div",{style:{width:`${subTabTimelineWidth}px`},className:"relative flex flex-col min-h-full"},/*#__PURE__*/React.createElement(TimelineRuler,{bpm:parseInt(bpm)||120,zoom:zoom,timelineWidth:subTabTimelineWidth,viewportWidth:viewportWidth,onPlayheadSet:setCurrentTime,snapValue:snapValue,onRulerMouseDown:e=>{const wrapper=timelineWrapperRef.current;if(!wrapper)return;const rect=wrapper.getBoundingClientRect();const sl=wrapper.scrollLeft;const raw=Math.max(0,(e.clientX-rect.left+sl)/zoom);const t=snapValue!=='free'?snapTime(raw,snapValue,bpm):raw;if(e.shiftKey){e.preventDefault();e.stopPropagation();}handlePlayheadSet(t);},scrollLeft:scrollLeft,canvasRedrawCount:canvasRedrawCount}),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col relative bg-[#111111] min-h-full"},vTrack&&/*#__PURE__*/React.createElement("div",{style:{height:`${subTabHeight}px`},className:"relative overflow-hidden border-2 border-purple-500/40 rounded bg-[#151515] mx-1 mt-1 shrink-0"},/*#__PURE__*/React.createElement(SubTabWaveform,{buffer:st.buffer,subTabId:st.id,activeTab:activeTab,activeTool:activeTool,currentTime:st.currentTime,selectionStart:st.selectionStart,selectionEnd:st.selectionEnd,onSelectRange:(start,end)=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,selectionStart:start,selectionEnd:end}:s)),onPlayheadSet:time=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,currentTime:time}:s)),onContextMenu:(e,clickTime)=>setContextMenu({x:e.clientX,y:e.clientY,isSubTab:true,subTabId:st.id,time:clickTime}),zoom:zoom,timelineWidth:subTabTimelineWidth,color:vTrack.color,name:vTrack.name,speed:st.speed||1.0,volumeNodes:st.volumeNodes||[],panningNodes:st.panningNodes||[],fadeInLen:st.fadeInLen||0,fadeOutLen:st.fadeOutLen||0,graphMode:st.graphMode,channelInfo:st.channelInfo,selectedNodeTime:subTabSelectedNodeTime,setSelectedNodeTime:setSubTabSelectedNodeTime,onUpdateNodes:nodes=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,[s.graphMode==='pan'?'panningNodes':'volumeNodes']:nodes}:s)),onUpdateFade:fade=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,fadeInLen:fade.fadeInLen??s.fadeInLen,fadeOutLen:fade.fadeOutLen??s.fadeOutLen}:s)),onModeToggle:()=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,graphMode:s.graphMode==='pan'?null:'pan'}:s)),onSpeedChange:newSpeed=>{setSubTabs(prev=>prev.map(s=>{if(s.id!==st.id)return s;const oldSpeed=s.speed||1.0;const ratio=oldSpeed/newSpeed;const newVolumeNodes=(s.volumeNodes||[]).map(n=>({...n,time:n.time*ratio}));const newPanningNodes=(s.panningNodes||[]).map(n=>({...n,time:n.time*ratio}));return{...s,speed:newSpeed,volumeNodes:newVolumeNodes,panningNodes:newPanningNodes,fadeInLen:(s.fadeInLen||0)*ratio,fadeOutLen:(s.fadeOutLen||0)*ratio,currentTime:(s.currentTime||0)*ratio,label:s.label.replace(/\s\(\d+%\)$/,'')+` (${Math.round(newSpeed*100)}%)`};}));const n=activeTrackNodesRef.current[st.trackId];if(n&&n.source)n.source.playbackRate.value=newSpeed;// Reset time refs to prevent playhead jump when speed changes mid-playback +const prefsRef=useRef({});prefsRef.current={showAIPanel,showExportPanel,showSelectionPanel,showPythonToolsPanel,showMediaExplorer,showFxRack,showMidiEvents,panelPositions,rightSidebarWidth,mediaExplorerHeight,selectedProviderId};useEffect(()=>{const prefs=prefsRef.current;localStorage.setItem('sonic_preferences',JSON.stringify(prefs));if(!currentUser||currentUser==='cached')return;const timer=setTimeout(async()=>{try{await window.SonicAPI.savePreferences(prefs);}catch(e){}},2000);return()=>clearTimeout(timer);},[showAIPanel,showExportPanel,showSelectionPanel,showPythonToolsPanel,showMediaExplorer,showFxRack,showMidiEvents,panelPositions,rightSidebarWidth,mediaExplorerHeight,selectedProviderId,currentUser]);return/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{className:"h-full w-full flex flex-col bg-[#1e1e1e]"},/*#__PURE__*/React.createElement("header",{className:"h-9 bg-[#2e2e2e] border-b border-[#181818] flex items-center px-1 shrink-0 select-none"},[{label:'File',items:[{label:'New Project',icon:'file-plus',shortcut:'Ctrl+N',action:()=>{setTracks([{id:'1',name:'Track 01',buffer:null,startTime:0,volumeDb:0,pan:0,muted:false,solo:false,color:'#0f766e',markers:[],serverFileId:null,clips:[],sections:[],midiItems:[]},{id:'2',name:'Track 02',buffer:null,startTime:0,volumeDb:0,pan:0,muted:false,solo:false,color:'#1d4ed8',markers:[],serverFileId:null,clips:[],sections:[],midiItems:[]}]);setSelectedTrackId('1');setProjectName('');setCurrentProjectId(null);localStorage.removeItem('sonic_project_name');localStorage.removeItem('sonic_project_id');showToast('New project created','info');}},{label:'Open Project...',icon:'folder-open',shortcut:'Ctrl+O',action:()=>handleImportSFS()},{label:'Save Project',icon:'upload-cloud',shortcut:'Ctrl+S',action:()=>handleSaveProject()},{label:'Save As...',icon:'download',shortcut:'Ctrl+Alt+S',action:()=>setSaveAsModalOpen(true)},{sep:true},{label:'Config AI Providers...',icon:'settings',action:()=>setAiConfigModalOpen(true)},{label:'Import Audio...',icon:'file-input',shortcut:'Ctrl+Alt+I',action:()=>{const input=document.createElement('input');input.type='file';input.accept='audio/*';input.onchange=async e=>{if(e.target.files[0]){addNewTrack();const newId=(tracks.length+1).toString();setTimeout(()=>loadFileOnTrack(newId,e.target.files[0]),100);}};input.click();showToast('Import audio','info');}},{label:'Export Mix...',icon:'file-output',action:()=>triggerWavExport()},{label:'Export MIDI...',icon:'music',action:()=>triggerMidiExport()},{sep:true},...(currentUser?[{label:'Profile',icon:'user',action:()=>setProfileModalOpen(true)}]:[]),...(currentUser&¤tUser.role==='admin'?[{label:'System Manager',icon:'settings',action:()=>setSystemManagerModalOpen(true)}]:[]),{label:'Logout',icon:'log-out',action:()=>handleLogout()}]},{label:'Edit',items:[{label:'Insert New Track',icon:'plus',shortcut:'Ctrl+I',action:addNewTrack},{label:'Insert Music to Track',icon:'music',shortcut:'Ctrl+Alt+I',action:()=>showToast('Select music file to insert','info')},{sep:true},{label:'Edit in New Tab',icon:'file-edit',shortcut:'Ctrl+E',action:()=>openTempTab()},{label:'Split at Playhead',icon:'scissors',shortcut:'S',action:()=>handleSplitTrack(selectedTrackId)},{label:'Merge Tracks',icon:'combine',shortcut:'Ctrl+M',action:()=>{handleMergeTracks();}},{sep:true},{label:'Undo',icon:'undo',shortcut:'Ctrl+Z',action:()=>{handleUndo();}},{label:'Redo',icon:'redo',shortcut:'Ctrl+Y',action:()=>{handleRedo();}},{sep:true},{label:'Copy',icon:'copy',shortcut:'Ctrl+C',action:()=>{handleCopyTrack();}},{label:'Cut',icon:'scissors',shortcut:'Ctrl+X',action:()=>{handleCutTrack();}},{label:'Paste',icon:'clipboard',shortcut:'Ctrl+V',action:handlePasteTrack},{sep:true},{label:'Delete Track',icon:'trash-2',shortcut:'Del',action:()=>{handleDeleteTrack();}}]},{label:'Insert',items:[...(!sessionTabs.some(s=>s.id===activeTab)?[{label:'Insert Section',icon:'folder-plus',action:insertSectionAtPlayhead}]:[]),{label:'Insert MIDI item',icon:'music',action:insertMidiItemAtPlayhead},{label:'Insert sound clip',icon:'file-input',action:insertSoundClipAtCursor},{label:'Insert track',icon:'plus',action:insertTrackBelow}]},{label:'View',items:[{label:'Master Track',icon:'disc',action:()=>showToast('Master track view','info')},{label:'Maker View',icon:'layout',action:()=>showToast('Maker view','info')},{label:'Mixer',icon:'sliders',action:()=>showToast('Mixer panel','info')},{label:'Tempo Track',icon:'timer',action:()=>showToast('Tempo track','info')},{label:'Video',icon:'film',action:()=>showToast('Video panel','info')},{label:'Media Explorer',icon:'folder-search',action:()=>showToast('Media explorer','info')}]},{label:'Tools',items:[{label:'Config AI Providers...',icon:'settings',action:()=>setAiConfigModalOpen(true)},{label:'AI MIDI Preset Manager...',icon:'sliders',action:()=>setAiPresetModalOpen(true)},{label:'DSP Tools Panel',icon:'wrench',action:()=>openPanel('python_tools')},{sep:true},{label:'Plugin Manager (SoundFont/VSTi)',icon:'zap',action:()=>{setPluginManagerModalOpen(true);window.SonicAPI.listPlugins().then(data=>setPluginsData(data)).catch(()=>{});}}]},{label:'Help',items:[{label:'About SonicForge',icon:'info',action:()=>showToast('SonicForge Studio v1.0 - Professional DAW','info')}]}].map(menu=>/*#__PURE__*/React.createElement("div",{key:menu.label,className:"relative"},/*#__PURE__*/React.createElement("button",{onClick:()=>setMenuOpen(menuOpen===menu.label?null:menu.label),className:`px-3 py-1 text-xs font-medium transition rounded ${menuOpen===menu.label?'bg-zinc-700 text-zinc-100':'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800'}`},menu.label),menuOpen===menu.label&&/*#__PURE__*/React.createElement("div",{className:`absolute top-full left-0 mt-0.5 bg-[#2a2a2a] border border-zinc-700 rounded-lg shadow-2xl py-1 z-50 ${menu.label==='Edit'?'w-72':'w-64'}`,onClick:()=>setMenuOpen(null)},menu.items.map((item,i)=>item.sep?/*#__PURE__*/React.createElement("div",{key:i,className:"h-px bg-zinc-700 my-1"}):/*#__PURE__*/React.createElement("button",{key:item.label,onClick:e=>{e.stopPropagation();item.action();setMenuOpen(null);},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":item.icon,className:"w-3.5 h-3.5 text-zinc-500 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},item.label),item.shortcut&&/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},item.shortcut)))))),/*#__PURE__*/React.createElement("div",{className:"flex-1"}),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2 px-2"},/*#__PURE__*/React.createElement("span",{className:`text-xs font-bold uppercase px-1.5 py-0.5 rounded ${serverStatus==='connected'?'bg-emerald-950 text-emerald-400':serverStatus==='checking'?'bg-amber-950 text-amber-400':'bg-red-950 text-red-400'}`},"Server: ",serverStatus),/*#__PURE__*/React.createElement("button",{onClick:()=>setShowAIConfig(!showAIConfig),className:`px-1.5 py-0.5 rounded text-xs border transition ${showAIConfig?'bg-purple-900 text-purple-200 border-purple-700':'bg-zinc-800 text-zinc-400 border-zinc-700 hover:text-zinc-200'}`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"cpu",className:"w-3 h-3"}))))),menuOpen&&/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-40",onClick:()=>setMenuOpen(null)}),/*#__PURE__*/React.createElement("div",{className:"h-7 bg-[#222] border-b border-zinc-800 flex items-stretch px-2 gap-0.5 shrink-0 overflow-x-auto"},/*#__PURE__*/React.createElement("button",{onClick:()=>setActiveTab('main'),className:`px-3 text-xs font-bold uppercase tracking-wider border-b-2 transition flex items-center gap-1 ${activeTab==='main'?'text-cyan-400 border-cyan-500 bg-zinc-800/50':'text-zinc-500 border-transparent hover:text-zinc-300 hover:bg-zinc-800/30'}`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"layout-dashboard",className:"w-3 h-3"}))," Main Session"),sessionTabs.map(st=>{const isTabActive=activeTab===st.id;const tabColor=st.color||(isTabActive?'#06b6d4':null);const borderStyle=isTabActive?{borderBottomColor:tabColor,color:tabColor}:st.color?{color:st.color,borderBottomColor:'transparent'}:{};return/*#__PURE__*/React.createElement("div",{key:st.id,className:"flex items-stretch"},/*#__PURE__*/React.createElement("button",{onClick:()=>setActiveTab(st.id),onAuxClick:e=>{if(e.button===1){e.preventDefault();closeSessionTab(st.id);}},onContextMenu:e=>{e.preventDefault();setTabContextMenu({x:e.clientX,y:e.clientY,tabId:st.id,tabType:'session'});},style:borderStyle,className:`px-2 text-xs font-medium border-b-2 transition flex items-center gap-1 ${isTabActive?'bg-zinc-800/50':'text-zinc-500 border-transparent hover:text-zinc-300 hover:bg-zinc-800/30'}`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"layers",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"max-w-[120px] truncate"},st.name),st.isDirty&&/*#__PURE__*/React.createElement("span",{className:"w-1.5 h-1.5 rounded-full bg-amber-500 ml-1",title:"Chưa lưu thay đổi"})),/*#__PURE__*/React.createElement("button",{onClick:()=>closeSessionTab(st.id),className:"px-1 text-zinc-600 hover:text-red-400 transition text-xs",title:"Close tab"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"}))));}),subTabs.map(st=>{const isTabActive=activeTab===st.id;const tabColor=st.color||(isTabActive?'#f59e0b':null);const borderStyle=isTabActive?{borderBottomColor:tabColor,color:tabColor}:st.color?{color:st.color,borderBottomColor:'transparent'}:{};const iconName=st.type==='PIANO_ROLL'?'music':'file-edit';return/*#__PURE__*/React.createElement("div",{key:st.id,className:"flex items-stretch"},/*#__PURE__*/React.createElement("button",{onClick:()=>setActiveTab(st.id),onAuxClick:e=>{if(e.button===1){e.preventDefault();closeSubTab(st.id);}},onContextMenu:e=>{e.preventDefault();setTabContextMenu({x:e.clientX,y:e.clientY,tabId:st.id,tabType:'sub'});},style:borderStyle,className:`px-2 text-xs font-medium border-b-2 transition flex items-center gap-1 ${isTabActive?'bg-zinc-800/50':'text-zinc-500 border-transparent hover:text-zinc-300 hover:bg-zinc-800/30'}`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":iconName,className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"max-w-[100px] truncate"},st.label),st.isDirty&&/*#__PURE__*/React.createElement("span",{className:"w-1.5 h-1.5 rounded-full bg-amber-500 ml-1",title:"Chưa lưu thay đổi"})),/*#__PURE__*/React.createElement("button",{onClick:()=>closeSubTab(st.id),className:"px-1 text-zinc-600 hover:text-red-400 transition text-xs",title:"Close tab"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"}))));})),showAIConfig&&/*#__PURE__*/React.createElement("div",{className:"bg-zinc-900 border-b border-purple-900 p-3 flex flex-col gap-2 transition-all"},/*#__PURE__*/React.createElement("div",{className:"text-xs font-bold text-purple-400 uppercase tracking-wider flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"cpu",className:"w-4 h-4"}))," Cấu hình cổng kết nối API"),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-2 text-xs"},/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1"},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500 font-bold uppercase"},"Endpoint Base URL"),/*#__PURE__*/React.createElement("input",{type:"text",value:aiConfig.baseUrl,onChange:e=>setAiConfig(prev=>({...prev,baseUrl:e.target.value})),className:"bg-zinc-850 text-zinc-200 p-1.5 rounded border border-zinc-800 focus:outline-none focus:border-purple-600 font-mono text-xs",placeholder:"https://api.openai.com/v1"})),/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1"},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500 font-bold uppercase"},"API Token Key"),/*#__PURE__*/React.createElement("input",{type:"password",value:aiConfig.apiKey,onChange:e=>setAiConfig(prev=>({...prev,apiKey:e.target.value})),className:"bg-zinc-850 text-zinc-200 p-1.5 rounded border border-zinc-800 focus:outline-none focus:border-purple-600 font-mono text-xs",placeholder:"sk-..."})),/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1"},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500 font-bold uppercase"},"Model Name"),/*#__PURE__*/React.createElement("input",{type:"text",value:aiConfig.model,onChange:e=>setAiConfig(prev=>({...prev,model:e.target.value})),className:"bg-zinc-850 text-zinc-200 p-1.5 rounded border border-zinc-800 focus:outline-none focus:border-purple-600 font-mono text-xs",placeholder:"gpt-4o-mini"})))),/*#__PURE__*/React.createElement("div",{className:"h-9 bg-[#222] border-b border-zinc-800 flex items-center px-3 gap-2 shrink-0 select-none"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1 bg-zinc-900 border border-zinc-700 rounded px-1.5 py-0.5 shadow-lg",title:"Kéo để di chuyển toolbar",style:{cursor:'grab'}},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-0.5 mr-1 text-zinc-600"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{setActiveTool('select');showToast('Select Tool','info');},className:`w-7 h-7 flex items-center justify-center rounded ${activeTool==='select'?'bg-cyan-700 text-white':'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800'}`,title:"Select Tool (V)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"mouse-pointer",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{setActiveTool('grab');showToast('Grab Tool','info');},className:`w-7 h-7 flex items-center justify-center rounded ${activeTool==='grab'?'bg-cyan-700 text-white':'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800'}`,title:"Grab Tool (H)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"hand",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-0.5 border border-zinc-700 rounded bg-zinc-850 px-0.5"},/*#__PURE__*/React.createElement("button",{onClick:()=>{setActiveTool('razor');showToast('Razor Tool','info');},className:`w-7 h-7 flex items-center justify-center rounded ${activeTool==='razor'?'bg-cyan-700 text-white':'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800'}`,title:"Razor Tool (C)"},/*#__PURE__*/React.createElement("svg",{className:"w-3.5 h-3.5 text-orange-400",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round"},/*#__PURE__*/React.createElement("path",{d:"M6 3h12a2 2 0 0 1 2 2v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"}),/*#__PURE__*/React.createElement("path",{d:"M4 9h16l-3 9H7z"}),/*#__PURE__*/React.createElement("circle",{cx:"12",cy:"6",r:"1"}))),/*#__PURE__*/React.createElement("button",{onClick:handleGlueTracks,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-purple-400 hover:bg-zinc-800",title:"Glue Clips"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"link",className:"w-3.5 h-3.5"})))),/*#__PURE__*/React.createElement("button",{onClick:()=>{setActiveTool('pen');showToast('Pen Tool','info');},className:`w-7 h-7 flex items-center justify-center rounded ${activeTool==='pen'?'bg-cyan-700 text-white':'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800'}`,title:"Pen Tool (P)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"pen-tool",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-700 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:handleCutTrack,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-red-400 hover:bg-zinc-800",title:"Cut (Ctrl+X)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:handleCopyTrack,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-blue-400 hover:bg-zinc-800",title:"Copy (Ctrl+C)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"copy",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:handlePasteTrack,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-emerald-400 hover:bg-zinc-800",title:"Paste (Ctrl+V)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"clipboard",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-700 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:addNewTrack,className:"px-2 py-1 bg-cyan-600 hover:bg-cyan-500 text-white font-semibold rounded text-xs flex items-center gap-1 shadow transition",title:"Thêm Track Mới (Ctrl+I)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus",className:"w-3.5 h-3.5"})),/*#__PURE__*/React.createElement("span",null,"Track")),sessionTabs.some(s=>s.id===activeTab)&&/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-700 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:()=>handleSaveSectionTab(activeTab),className:"px-2 py-1 bg-emerald-600 hover:bg-emerald-500 text-white font-semibold rounded text-xs flex items-center gap-1 shadow transition",title:"Lưu Section vào Main Session"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"save",className:"w-3.5 h-3.5"})),/*#__PURE__*/React.createElement("span",null,"Lưu Section"))),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-700 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:handleUndo,disabled:undoStack.length===0,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800 disabled:opacity-30",title:"Undo (Ctrl+Z)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"undo",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:handleRedo,disabled:redoStack.length===0,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800 disabled:opacity-30",title:"Redo (Ctrl+Y)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"redo",className:"w-3.5 h-3.5"})))),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-800 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:()=>{const isSubTab=subTabs.some(sub=>sub.id===activeTab);if(isSubTab){setSubTabs(prev=>prev.map(s=>s.id===activeTab?{...s,currentTime:0}:s));}else{setCurrentTime(0);}},className:"w-7 h-7 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Quay lại đầu"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"skip-back",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{const isSubTab=subTabs.some(sub=>sub.id===activeTab);if(isSubTab){setSubTabs(prev=>prev.map(s=>{if(s.id!==activeTab)return s;const left=s.selectionStart!==null&&s.selectionEnd!==null?Math.min(s.selectionStart,s.selectionEnd):null;return left!==null?{...s,currentTime:left}:s;}));}else{if(selLeft!==null)setCurrentTime(selLeft);}},className:"w-7 h-7 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Đầu vùng chọn"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"step-back",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:handlePlayPause,className:`w-7 h-7 flex items-center justify-center rounded border transition ${isPlaying?'bg-emerald-600 text-black border-emerald-500 hover:bg-emerald-500':'bg-cyan-600 text-white border-cyan-500 hover:bg-cyan-500'}`,title:isPlaying?"Tạm dừng":"Play"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":isPlaying?"pause":"play",className:"w-3.5 h-3.5 fill-current"}))),/*#__PURE__*/React.createElement("button",{onClick:handleStop,className:"w-7 h-7 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Stop"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"square",className:"w-3.5 h-3.5 fill-current"}))),/*#__PURE__*/React.createElement("button",{onClick:handleRecordClick,className:`w-7 h-7 flex items-center justify-center rounded border transition ${recordingState==='RECORDING'?'bg-red-600 text-white border-red-500 hover:bg-red-500 animate-pulse':recordingState==='COUNT_IN'?'bg-amber-500 text-black border-amber-400 hover:bg-amber-400 animate-pulse':'bg-zinc-800 text-red-500 border-zinc-700 hover:bg-zinc-700 hover:text-red-400'}`,title:recordingState==='RECORDING'?"Đang ghi âm...":recordingState==='COUNT_IN'?"Chuẩn bị ghi âm...":"Ghi âm (Record)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"circle",className:"w-3.5 h-3.5 fill-current"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{const isSubTab=subTabs.some(sub=>sub.id===activeTab);if(isSubTab){setSubTabs(prev=>prev.map(s=>{if(s.id!==activeTab)return s;const right=s.selectionStart!==null&&s.selectionEnd!==null?Math.max(s.selectionStart,s.selectionEnd):null;return right!==null?{...s,currentTime:right}:s;}));}else{if(selRight!==null)setCurrentTime(selRight);}},className:"w-7 h-7 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Cuối vùng chọn"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"step-forward",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{const isSubTab=subTabs.some(sub=>sub.id===activeTab);if(isSubTab){setSubTabs(prev=>prev.map(s=>{if(s.id!==activeTab)return s;const duration=s.buffer?s.buffer.duration/(s.speed||1.0):0;return{...s,currentTime:duration};}));}else{setCurrentTime(maxDuration);}},className:"w-7 h-7 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Đến cuối"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"skip-forward",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-800 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:()=>setIsLoopingSelection(prev=>!prev),className:`w-7 h-7 flex items-center justify-center rounded border transition ${isLoopingSelection?'bg-amber-600 text-black border-amber-500 hover:bg-amber-500':'bg-zinc-800 text-zinc-200 border-zinc-700 hover:bg-zinc-700'}`,title:isLoopingSelection?selLeft!==null&&selRight!==null?"Loop vùng chọn":"Loop timeline":"Bật loop"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"repeat",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500 font-bold uppercase ml-2"},"Snap"),/*#__PURE__*/React.createElement("select",{value:snapValue,onChange:e=>setSnapValue(e.target.value),className:"bg-black text-white text-[14px] px-1.5 py-0.5 rounded border border-zinc-700 focus:outline-none focus:border-cyan-500 font-mono cursor-pointer"},/*#__PURE__*/React.createElement("option",{value:"free"},"Free"),/*#__PURE__*/React.createElement("option",{value:"1"},"1"),/*#__PURE__*/React.createElement("option",{value:"1/2"},"1/2"),/*#__PURE__*/React.createElement("option",{value:"1/4"},"1/4"),/*#__PURE__*/React.createElement("option",{value:"1/8"},"1/8"),/*#__PURE__*/React.createElement("option",{value:"1/16"},"1/16"),/*#__PURE__*/React.createElement("option",{value:"1/32"},"1/32"),/*#__PURE__*/React.createElement("option",{value:"4"},"4")),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-6 bg-zinc-800 mx-1.5"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500 font-bold"},"Bars:"),/*#__PURE__*/React.createElement("input",{type:"number",min:"0",value:beginBar,onChange:e=>{const b=parseInt(e.target.value)||0;setBeginBar(b);const beatDuration=60/parseInt(bpm||120);const t=b*beatDuration*4;clearLocalSelection();setSelectionMode('global');setSelectionStart(t);setSelectionEnd(t+beatDuration*4);},className:"w-14 bg-black text-white text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500"},"-"),/*#__PURE__*/React.createElement("input",{type:"number",min:"0",value:endBar,onChange:e=>{const b=parseInt(e.target.value)||0;setEndBar(b);const beatDuration=60/parseInt(bpm||120);const t=b*beatDuration*4;setSelectionEnd(t+beatDuration*4);setNumberBar(b-beginBar+1);},className:"w-14 bg-black text-white text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500"},"#"),/*#__PURE__*/React.createElement("input",{type:"number",min:"1",value:numberBar,readOnly:true,className:"w-14 bg-black text-zinc-400 text-[14px] px-1 py-0.5 rounded border border-zinc-800 text-center font-mono"}),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-6 bg-zinc-800 mx-1.5"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500"},"Start:"),/*#__PURE__*/React.createElement("input",{type:"text",value:selLeft!==null?formatTime(selLeft):'',onChange:e=>{const parts=e.target.value.split(/[:.]/);if(parts.length===3){const secs=parseInt(parts[0])*60+parseInt(parts[1])+parseFloat('0.'+(parts[2]||'0'));clearLocalSelection();setSelectionMode('global');setSelectionStart(secs);}},className:"w-20 bg-black text-zinc-200 text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500"},"End:"),/*#__PURE__*/React.createElement("input",{type:"text",value:selRight!==null?formatTime(selRight):'',onChange:e=>{const parts=e.target.value.split(/[:.]/);if(parts.length===3){const secs=parseInt(parts[0])*60+parseInt(parts[1])+parseFloat('0.'+(parts[2]||'0'));setSelectionEnd(secs);}},className:"w-20 bg-black text-zinc-200 text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500"},"Len:"),/*#__PURE__*/React.createElement("input",{type:"text",value:selLeft!==null&&selRight!==null?formatTime(Math.abs(selRight-selLeft)):'',onChange:e=>{const parts=e.target.value.split(/[:.]/);if(parts.length===3&&selLeft!==null){const secs=parseInt(parts[0])*60+parseInt(parts[1])+parseFloat('0.'+(parts[2]||'0'));setSelectionEnd(selLeft+secs);}},className:"w-20 bg-black text-amber-300 text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono"}),/*#__PURE__*/React.createElement("div",{className:"flex-1"}),/*#__PURE__*/React.createElement("div",{className:"text-xs font-bold font-mono text-zinc-100"},formatTime(currentTime))),(()=>{const dockPanels={top:[],right:[],bottom:[],left:[]};const addPanel=(id,pos,visible)=>{if(visible)dockPanels[pos].push(id);};addPanel('export',panelPositions.export,showExportPanel);addPanel('ai',panelPositions.ai,showAIPanel);addPanel('python_tools',panelPositions.python_tools||'bottom',showPythonToolsPanel);addPanel('selection',panelPositions.selection,showSelectionPanel);addPanel('media_explorer','bottom',showMediaExplorer);addPanel('fx_rack',panelPositions.fx_rack||'bottom',showFxRack);addPanel('midi_events',panelPositions.midi_events||'bottom',showMidiEvents);const closePanel=id=>{if(id==='export')setShowExportPanel(false);else if(id==='ai')setShowAIPanel(false);else if(id==='python_tools')setShowPythonToolsPanel(false);else if(id==='selection')setShowSelectionPanel(false);else if(id==='media_explorer')setShowMediaExplorer(false);else if(id==='fx_rack')setShowFxRack(false);else if(id==='midi_events')setShowMidiEvents(false);};const renderPanelContent=panelId=>{const h=id=>e=>{startPanelDrag(id,e);};if(panelId==='export')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('export',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-zinc-200 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"save",className:"w-3.5 h-3.5 text-cyan-400"}))," Export"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('export'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Ngu\u1ed3n"),/*#__PURE__*/React.createElement("select",{value:exportSettings.source,onChange:e=>setExportSettings(p=>({...p,source:e.target.value})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"project"},"Project (Mix)"),/*#__PURE__*/React.createElement("option",{value:"track_mix"},"Track Selection"),/*#__PURE__*/React.createElement("option",{value:"active_clip"},"Active Clip"),/*#__PURE__*/React.createElement("option",{value:"clip_selection"},"Clip Selection"))),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"\u0110\u1ecbnh d\u1ea1ng"),/*#__PURE__*/React.createElement("select",{value:exportSettings.format,onChange:e=>setExportSettings(p=>({...p,format:e.target.value,sampleRate:e.target.value==='wav'?'44100':e.target.value==='mp3'?'44100':'44100',bitDepth:e.target.value==='wav'?'16':'16',quality:'44khz'})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"wav"},"WAV"),/*#__PURE__*/React.createElement("option",{value:"mp3"},"MP3"),/*#__PURE__*/React.createElement("option",{value:"ogg"},"OGG")))),exportSettings.format==='wav'?/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"SR (Hz)"),/*#__PURE__*/React.createElement("select",{value:exportSettings.sampleRate,onChange:e=>setExportSettings(p=>({...p,sampleRate:e.target.value})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"22500"},"22500"),/*#__PURE__*/React.createElement("option",{value:"44100"},"44100"))),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Bit"),/*#__PURE__*/React.createElement("select",{value:exportSettings.bitDepth,onChange:e=>setExportSettings(p=>({...p,bitDepth:e.target.value})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"8"},"8"),/*#__PURE__*/React.createElement("option",{value:"16"},"16"),/*#__PURE__*/React.createElement("option",{value:"24"},"24")))):/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Ch\u1ea5t l\u01b0\u1ee3ng"),/*#__PURE__*/React.createElement("select",{value:exportSettings.quality,onChange:e=>setExportSettings(p=>({...p,quality:e.target.value})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"44khz"},"44kHz"),/*#__PURE__*/React.createElement("option",{value:"lossless"},"Lossless"))),/*#__PURE__*/React.createElement("div",null)),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Kênh"),/*#__PURE__*/React.createElement("select",{value:exportSettings.channels,onChange:e=>setExportSettings(p=>({...p,channels:e.target.value})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"mono"},"Mono"),/*#__PURE__*/React.createElement("option",{value:"stereo"},"Stereo"))),/*#__PURE__*/React.createElement("div",null)),/*#__PURE__*/React.createElement("button",{onClick:triggerWavExport,disabled:isExporting,className:"w-full py-1 bg-cyan-700 hover:bg-cyan-600 text-zinc-100 font-bold rounded text-xs flex items-center justify-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"download-cloud",className:"w-3 h-3"})),isExporting?'...':'Export'));if(panelId==='ai')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1.5 flex-1 min-h-0"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('ai',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-zinc-200 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"cpu",className:"w-3.5 h-3.5 text-purple-400"}))," AI Copilot"),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("button",{onClick:()=>setAiPresetModalOpen(true),className:"text-zinc-600 hover:text-zinc-300 mr-0.5",title:"Preset Manager"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sliders",className:"w-3 h-3"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{setAiActionLog([]);showToast('Đã xoá nhật ký AI.','info');},className:"text-zinc-600 hover:text-zinc-300",title:"Clear log"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"trash-2",className:"w-3 h-3"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('ai'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"}))))),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1.5 w-full min-w-0 pb-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"cpu",className:"w-3 h-3 text-purple-400"})),/*#__PURE__*/React.createElement("select",{value:selectedProviderId,onChange:e=>setSelectedProviderId(e.target.value),className:"flex-1 min-w-0 max-w-full bg-[#141414] text-zinc-200 border border-zinc-700 rounded px-1 py-0.5 text-xs font-mono focus:outline-none focus:border-purple-600 truncate"},aiProviders.length===0?/*#__PURE__*/React.createElement("option",{value:""},"Chưa có provider"):aiProviders.map(p=>/*#__PURE__*/React.createElement("option",{key:p.id,value:p.id},p.name,p.is_active?'':' (inactive)')))),/*#__PURE__*/React.createElement("div",{className:"border-t border-zinc-800 pt-1 mt-1 shrink-0"},/*#__PURE__*/React.createElement("button",{onClick:()=>{if(window.DAWCommandDispatcher&&window.DAWCommandDispatcher.undo){const entry=window.DAWCommandDispatcher.undo();if(entry){setAiActionLog(prev=>[...prev,{type:'undo',text:`Undo: ${entry.name}`,time:Date.now()}]);showToast(`Undo AI: ${entry.name}`,'info');}}else{handleUndo();setAiActionLog(prev=>[...prev,{type:'undo',text:'Undo (Ctrl+Z)',time:Date.now()}]);}},className:"w-full text-[10px] text-amber-400 hover:text-amber-300 border border-amber-800 rounded py-0.5"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center justify-center gap-1"},/*#__PURE__*/React.createElement("i",{"data-lucide":"rotate-ccw",className:"w-3 h-3"}),"Undo"))),/*#__PURE__*/React.createElement("div",{className:"flex-1 min-h-0 flex flex-col overflow-hidden mt-1"},/*#__PURE__*/React.createElement("div",{className:"text-[10px] font-bold text-zinc-400 uppercase shrink-0 pb-0.5"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center gap-1"},/*#__PURE__*/React.createElement("i",{"data-lucide":"list",className:"w-3 h-3"})," Action Log")),/*#__PURE__*/React.createElement("div",{ref:actionLogContainerRef,className:"flex-1 overflow-y-auto no-scrollbar bg-[#0f0f0f] rounded border border-zinc-800 select-text"},aiActionLog.length===0?/*#__PURE__*/React.createElement("div",{className:"text-xs text-zinc-600 italic select-text"},"Chưa có hành động nào."):aiActionLog.map((entry,i)=>/*#__PURE__*/React.createElement("div",{key:i,className:`text-xs font-mono py-0.5 border-b border-zinc-900 last:border-0 ${entry.type==='error'?'text-red-400':entry.type==='status'?'text-zinc-400 italic':entry.type==='undo'?'text-amber-400':'text-zinc-300'}`},new Date(entry.time).toLocaleTimeString(),entry.text)))),/*#__PURE__*/React.createElement("div",{className:"border-t border-zinc-800 pt-1.5 mt-1 shrink-0"},/*#__PURE__*/React.createElement("div",{className:"text-xs font-bold text-zinc-400 uppercase mb-1 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"message-square",className:"w-3 h-3"}))," Copilot Prompt"),/*#__PURE__*/React.createElement("textarea",{value:aiPrompt,onChange:e=>setAiPrompt(e.target.value),placeholder:"Nhập lệnh điều khiển DAW... (VD: Tạo track mới tên Beat, đặt BPM 128)",className:"w-full bg-[#1e1e1e] text-zinc-200 p-1.5 rounded border border-zinc-700 focus:outline-none focus:border-purple-600 font-mono text-xs resize-none",rows:2,onKeyDown:e=>{if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();handleAISend();}else if(e.key==='ArrowUp'&&promptHistRef.current.length>0){e.preventDefault();const idx=promptHistIdx===-1?promptHistRef.current.length-1:Math.max(0,promptHistIdx-1);setPromptHistIdx(idx);setAiPrompt(promptHistRef.current[idx]);}else if(e.key==='ArrowDown'){e.preventDefault();if(promptHistIdx===-1)return;const idx=promptHistIdx+1;if(idx>=promptHistRef.current.length){setPromptHistIdx(-1);setAiPrompt('');}else{setPromptHistIdx(idx);setAiPrompt(promptHistRef.current[idx]);}}}})),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1 mt-1 shrink-0"},/*#__PURE__*/React.createElement("button",{onClick:handleAISend,disabled:aiProcessing,className:"flex-1 py-1 bg-purple-700 hover:bg-purple-600 text-white font-bold rounded text-xs border border-purple-500 flex items-center justify-center gap-1"},aiProcessing?'Đang suy luận...':/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"send",className:"w-3 h-3"}))," Gửi")),/*#__PURE__*/React.createElement("button",{onClick:()=>{setAiPrompt('');setAiActionLog([]);},className:"px-2 py-1 bg-zinc-800 hover:bg-zinc-700 text-zinc-400 rounded text-xs border border-zinc-700"},"Clear")),/*#__PURE__*/React.createElement("div",{className:"text-xs text-zinc-600 shrink-0"},"Enter để gửi nhanh"));if(panelId==='python_tools')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('python_tools',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-amber-300 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"wrench",className:"w-3.5 h-3.5 text-amber-400"}))," DSP Tools"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('python_tools'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"p-1.5 bg-[#141414] rounded border border-zinc-800 text-[10px] font-mono text-zinc-400 space-y-0.5 leading-relaxed"},dspSelectionStats?[/*#__PURE__*/React.createElement("div",{key:"track"},`Track: ${dspSelectionStats.trackName}`),/*#__PURE__*/React.createElement("div",{key:"range"},`Range: ${dspSelectionStats.timeRange}`),/*#__PURE__*/React.createElement("div",{key:"ch"},`Channels: ${dspSelectionStats.channels}`),/*#__PURE__*/React.createElement("div",{key:"peak"},`Peak Vol: ${dspSelectionStats.peakVolume}`)]:"Chưa chọn track"),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1 text-xs"},/*#__PURE__*/React.createElement("button",{onClick:()=>runPythonTool('normalize'),className:"py-1 bg-amber-950/80 hover:bg-amber-900 text-amber-300 border border-amber-800/80 rounded font-bold flex items-center justify-center gap-1"},"⚡ Peak Norm (0dB)"),/*#__PURE__*/React.createElement("button",{onClick:()=>runPythonTool('invert_phase'),className:"py-1 bg-zinc-800 hover:bg-zinc-700 text-zinc-200 border border-zinc-700 rounded font-bold flex items-center justify-center gap-1"},"🔄 Phase Invert"),/*#__PURE__*/React.createElement("button",{onClick:()=>runPythonTool('swap_channels'),className:"py-1 bg-zinc-800 hover:bg-zinc-700 text-zinc-200 border border-zinc-700 rounded font-bold flex items-center justify-center gap-1"},"🔀 Swap L/R"),/*#__PURE__*/React.createElement("button",{onClick:()=>runPythonTool('synth_wave'),className:"py-1 bg-teal-950/80 hover:bg-teal-900 text-teal-300 border border-teal-800/80 rounded font-bold flex items-center justify-center gap-1"},"🎹 Gen Synth Tone")));if(panelId==='selection')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('selection',e)},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500 font-bold uppercase flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"}))," Selection"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('selection'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-3 gap-1 bg-[#141414] p-1.5 rounded border border-zinc-800"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("span",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Start"),/*#__PURE__*/React.createElement("input",{type:"number",step:"0.01",value:selectionStats.start,onChange:e=>handleSelectionInputChange('start',e.target.value),className:"w-full bg-[#242424] text-amber-400 text-center font-mono text-xs rounded py-0.5 border border-zinc-700 focus:outline-none"})),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("span",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"End"),/*#__PURE__*/React.createElement("input",{type:"number",step:"0.01",value:selectionStats.end,onChange:e=>handleSelectionInputChange('end',e.target.value),className:"w-full bg-[#242424] text-amber-400 text-center font-mono text-xs rounded py-0.5 border border-zinc-700 focus:outline-none"})),/*#__PURE__*/React.createElement("div",{className:"flex flex-col justify-center"},/*#__PURE__*/React.createElement("span",{className:"text-[7px] text-zinc-500 font-bold uppercase"},"Len"),/*#__PURE__*/React.createElement("span",{className:"text-zinc-200 font-mono text-xs font-semibold mt-0.5"},selectionStats.length,"s"))),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-3 gap-1 bg-[#141414] p-1.5 rounded border border-zinc-800 mt-1"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("span",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Begin Bar"),/*#__PURE__*/React.createElement("input",{type:"number",min:"0",value:beginBar,onChange:e=>{const b=parseInt(e.target.value)||0;setBeginBar(b);const beatDuration=60/parseInt(bpm||120);const t=b*beatDuration*4;clearLocalSelection();setSelectionMode('global');setSelectionStart(t);setSelectionEnd(t+beatDuration*4);},className:"w-full bg-[#242424] text-white text-center font-mono text-xs rounded py-0.5 border border-zinc-700 focus:outline-none"})),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("span",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"End Bar"),/*#__PURE__*/React.createElement("input",{type:"number",min:"0",value:endBar,onChange:e=>{const b=parseInt(e.target.value)||0;setEndBar(b);const beatDuration=60/parseInt(bpm||120);const t=b*beatDuration*4;setSelectionEnd(t+beatDuration*4);setNumberBar(b-beginBar+1);},className:"w-full bg-[#242424] text-white text-center font-mono text-xs rounded py-0.5 border border-zinc-700 focus:outline-none"})),/*#__PURE__*/React.createElement("div",{className:"flex flex-col justify-center"},/*#__PURE__*/React.createElement("span",{className:"text-[7px] text-zinc-500 font-bold uppercase"},"# Bars"),/*#__PURE__*/React.createElement("span",{className:"text-zinc-200 font-mono text-xs font-semibold mt-0.5"},numberBar))));if(panelId==='media_explorer')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('media_explorer',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-emerald-300 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"folder-open",className:"w-3.5 h-3.5 text-emerald-400"}))," Media Explorer"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('media_explorer'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"flex-1 overflow-y-auto text-xs text-zinc-400 font-mono p-2"},"// Placeholder: Media files browser"));if(panelId==='fx_rack')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('fx_rack',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-rose-300 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sliders",className:"w-3.5 h-3.5 text-rose-400"}))," Plugin FX Rack"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('fx_rack'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"flex-1 text-xs text-zinc-500 italic flex items-center justify-center"},"No FX plugins loaded"));if(panelId==='midi_events')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('midi_events',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-sky-300 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"music",className:"w-3.5 h-3.5 text-sky-400"}))," MIDI Event List"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('midi_events'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"flex-1 text-xs text-zinc-500 italic flex items-center justify-center"},"No MIDI events selected"));return null;};const renderDock=(pos,title)=>{const panels=dockPanels[pos];if(panels.length===0)return null;const isSide=pos==='left'||pos==='right';const borderClass=pos==='left'?'border-r':pos==='right'?'border-l':pos==='top'?'border-b':'border-t';const bgClass='bg-[#1e1e1e]';const highlight=panelDragRef.current&&panelDropZone===pos;if(pos==='right')return/*#__PURE__*/React.createElement("div",{id:"right-sidebar",className:`${borderClass} ${bgClass} flex flex-col overflow-hidden select-none h-full`,style:{width:`${rightSidebarWidth}px`,minWidth:'200px',maxWidth:'600px',flexShrink:0}},/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col gap-2 p-2 overflow-hidden h-full"},panels.map((p,idx)=>/*#__PURE__*/React.createElement(React.Fragment,{key:p},/*#__PURE__*/React.createElement("div",{className:'flex flex-col flex-1 min-h-0 border border-zinc-700 rounded-lg bg-[#262626] shadow-sm p-3'},renderPanelContent(p)),idx/*#__PURE__*/React.createElement("div",{key:p,className:`${isSide?'w-full':'flex-none w-[320px]'} border border-zinc-700 rounded-lg bg-[#262626] shadow-sm p-2`},renderPanelContent(p))));};return/*#__PURE__*/React.createElement("div",{ref:workspaceRef,className:"flex-1 flex flex-col overflow-hidden select-none daw-bg relative"},panelDragRef.current&&panelDropZone&&/*#__PURE__*/React.createElement("div",{className:"absolute inset-0 z-50 pointer-events-none"},panelDropZone==='top'&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 left-0 right-0 h-1 bg-cyan-400 shadow-[0_0_8px_#06b6d4]"}),panelDropZone==='bottom'&&/*#__PURE__*/React.createElement("div",{className:"absolute bottom-0 left-0 right-0 h-1 bg-cyan-400 shadow-[0_0_8px_#06b6d4]"}),panelDropZone==='left'&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 left-0 w-1 bg-cyan-400 shadow-[0_0_8px_#06b6d4]"}),panelDropZone==='right'&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 right-0 w-1 bg-cyan-400 shadow-[0_0_8px_#06b6d4]"})),dragGhostPanel&&dragGhostPos&&/*#__PURE__*/React.createElement("div",{className:"fixed z-[100] pointer-events-none opacity-80 border border-cyan-500 rounded-lg bg-[#262626] shadow-2xl p-3 w-56",style:{left:dragGhostPos.x,top:dragGhostPos.y}},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2 text-xs text-zinc-200 font-bold"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"move",className:"w-3.5 h-3.5 text-cyan-400"})),dragGhostPanel==='export'?'Export Panel':dragGhostPanel==='ai'?'AI Panel':dragGhostPanel==='python_tools'?'Audio Processing Panel':'Selection Panel'),/*#__PURE__*/React.createElement("div",{className:"text-xs text-zinc-500 mt-1"},"Drop at edge to dock")),renderDock('top','Top'),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex overflow-hidden"},renderDock('left','Left'),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col overflow-hidden min-w-0"},/*#__PURE__*/React.createElement("div",{className:"flex-1 flex overflow-hidden"},activeTab==='main'||sessionTabs.some(s=>s.id===activeTab)?/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{ref:tcpContainerRef,onScroll:handleTCPScroll,className:"shrink-0 z-20 bg-[#262626] overflow-y-auto flex flex-col border-r border-zinc-900 no-scrollbar",style:{width:tcpWidth+'px',scrollbarWidth:'none',msOverflowStyle:'none'}},/*#__PURE__*/React.createElement("div",{className:"sticky top-0 z-50 flex items-center justify-between h-10 border-b border-zinc-900 bg-[#242424] px-2 shrink-0"},/*#__PURE__*/React.createElement("span",{className:"text-xs font-bold text-zinc-300 flex items-center gap-1.5"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sliders",className:"w-3.5 h-3.5 text-cyan-400"})),"TRACKS (",activeTracks.length,")"),/*#__PURE__*/React.createElement("button",{onClick:addNewTrack,className:"px-2.5 py-1 bg-cyan-600 hover:bg-cyan-500 text-white rounded text-xs font-semibold flex items-center gap-1 shadow transition"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus",className:"w-3 h-3"}))," Add Track")),/*#__PURE__*/React.createElement("div",{className:"sticky top-10 z-40 flex h-[40px] border-b border-purple-500/30 bg-[#1a1a2e] p-2 border-l-4 border-purple-500 shrink-0"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between w-full"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"text-xs font-bold text-purple-400 font-mono"},"TM"),/*#__PURE__*/React.createElement("span",{className:"text-xs font-semibold text-zinc-300"},"Tempo")),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("input",{type:"number",value:bpm,onChange:e=>setBpm(e.target.value),onBlur:()=>localStorage.setItem('studio_bpm',bpm),className:"w-12 bg-zinc-800 border border-zinc-700 rounded text-xs text-zinc-300 text-center font-mono focus:outline-none focus:border-purple-500",min:"40",max:"300"}),/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500"},"BPM")))),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col divide-y divide-[#141414] bg-[#262626]"},activeTracks.length===0?/*#__PURE__*/React.createElement("div",{className:"p-6 text-center text-zinc-400 flex flex-col items-center justify-center space-y-3"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus-circle",className:"w-8 h-8 text-cyan-400 opacity-80"})),/*#__PURE__*/React.createElement("p",{className:"text-xs font-medium"},"Chưa có Track nào trong dự án."),/*#__PURE__*/React.createElement("button",{onClick:addNewTrack,className:"px-3 py-1.5 bg-cyan-600 hover:bg-cyan-500 text-white rounded text-xs font-semibold flex items-center gap-1.5 shadow"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus-circle",className:"w-3.5 h-3.5"}))," Thêm Track Mới")):activeTracks.map((track,idx)=>{const isSelected=selectedTrackId===track.id;const autoHeight=track.height||(track.isArmed?164:140);return/*#__PURE__*/React.createElement("div",{key:track.id,style:{height:`${autoHeight}px`},className:`shrink-0 relative flex flex-col justify-between p-2.5 bg-[#1e1e1e] border-r border-zinc-900 cursor-pointer border-l-4 border-b border-[#141414] overflow-hidden ${isSelected?'border-cyan-500 bg-[#252525]':'border-transparent hover:bg-zinc-800/20'}`,onClick:()=>setSelectedTrackId(track.id)},/*#__PURE__*/React.createElement("div",{className:"flex items-start justify-between"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"text-xs font-bold text-zinc-500 font-mono"},(idx+1).toString().padStart(2,'0')),/*#__PURE__*/React.createElement("label",{onClick:e=>{e.stopPropagation();const el=e.currentTarget.querySelector('input');if(el)el.click();},className:"cursor-pointer"},/*#__PURE__*/React.createElement("input",{type:"color",value:track.color||'#0f766e',onChange:e=>{e.stopPropagation();updateTrackColor(track.id,e.target.value);},className:"w-0 h-0 opacity-0 absolute pointer-events-none"}),/*#__PURE__*/React.createElement("div",{className:"w-3 h-3 rounded-full border border-zinc-600 hover:scale-110 transition-transform",style:{backgroundColor:track.color}})),editingTrackName===track.id?/*#__PURE__*/React.createElement("input",{type:"text",value:editNameInput,autoFocus:true,onChange:e=>setEditNameInput(e.target.value),onBlur:()=>{updateTrackName(track.id,editNameInput||track.name);setEditingTrackName(null);},onKeyDown:e=>{if(e.key==='Enter'){updateTrackName(track.id,editNameInput||track.name);setEditingTrackName(null);}if(e.key==='Escape')setEditingTrackName(null);},onClick:e=>e.stopPropagation(),className:"text-xs font-semibold bg-black text-zinc-200 border border-cyan-500 rounded px-1 py-0 w-24 outline-none"}):/*#__PURE__*/React.createElement("span",{className:"text-xs font-semibold text-zinc-300 truncate max-w-[80px] cursor-text hover:text-cyan-300 transition-colors",title:"Click to rename",onClick:e=>{e.stopPropagation();setEditingTrackName(track.id);setEditNameInput(track.name);}},track.name)),/*#__PURE__*/React.createElement("div",{className:"flex flex-wrap gap-0.5 max-w-[100px] mb-0.5"},(track.clips&&track.clips.length>0?track.clips:track.buffer?[{id:'default',name:track.name,startTime:track.startTime}]:[]).slice(0,3).map(c=>/*#__PURE__*/React.createElement("span",{key:c.id,className:"text-[9px] font-mono text-zinc-500 bg-zinc-800/60 rounded px-0.5 truncate max-w-[90px] cursor-pointer hover:text-cyan-400 hover:bg-zinc-700",title:c.name||track.name,onClick:e=>{e.stopPropagation();setSelectedTrackId(track.id);clearLocalSelection();setSelectionMode('global');const start=c.startTime||0;const end=start+(c.buffer?c.buffer.duration:2);setSelectionStart(start);setSelectionEnd(end);showToast(`Selected: ${c.name||track.name}`,'info');}},c.name||track.name),editingClipName&&editingClipName.trackId===track.id&&editingClipName.clipId===c.id?/*#__PURE__*/React.createElement("input",{type:"text",value:editNameInput,autoFocus:true,onChange:e=>setEditNameInput(e.target.value),onBlur:()=>{if(editNameInput.trim())updateClipName(track.id,c.id,editNameInput.trim());setEditingClipName(null);},onKeyDown:e=>{if(e.key==='Enter'){if(editNameInput.trim())updateClipName(track.id,c.id,editNameInput.trim());setEditingClipName(null);}if(e.key==='Escape')setEditingClipName(null);},onClick:e=>e.stopPropagation(),className:"w-20 text-[9px] font-mono bg-black text-cyan-300 border border-cyan-500 rounded px-0.5 py-0 outline-none"}):/*#__PURE__*/React.createElement("button",{className:"text-[9px] text-zinc-600 hover:text-cyan-400 ml-0.5 shrink-0",title:"Sửa tên clip",onClick:e=>{e.stopPropagation();setEditingClipName({trackId:track.id,clipId:c.id});setEditNameInput(c.name||track.name);}},/*#__PURE__*/React.createElement("i",{"data-lucide":"pencil",className:"w-2.5 h-2.5"})))),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackMute(track.id);},title:"Mute",className:`px-1.5 py-0.5 text-[10px] rounded font-mono font-bold border transition flex items-center gap-0.5 ${track.muted?'bg-red-950 text-red-400 border-red-700':'bg-zinc-800 text-zinc-400 border-transparent hover:text-zinc-200'}`},/*#__PURE__*/React.createElement("i",{"data-lucide":track.muted?"volume-x":"volume-2",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackSoloEvaluate(track.id);},title:"Solo",className:`px-1.5 py-0.5 text-[10px] rounded font-mono font-bold border transition flex items-center gap-0.5 ${soloedTrackId===track.id||track.solo?'bg-amber-950 text-amber-400 border-amber-600':'bg-zinc-800 text-zinc-400 border-transparent hover:text-zinc-200'}`},/*#__PURE__*/React.createElement("i",{"data-lucide":soloedTrackId===track.id||track.solo?"headphones":"headphone-off",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackArm(track.id);},title:"ARM (Record)",className:`px-1.5 py-0.5 text-[10px] rounded font-mono font-bold border transition flex items-center gap-0.5 ${track.isArmed?'bg-red-600 text-white border-red-500 hover:bg-red-500':'bg-zinc-800 text-zinc-400 border-transparent hover:text-zinc-200'}`},/*#__PURE__*/React.createElement("i",{"data-lucide":"circle",className:`w-2.5 h-2.5 ${track.isArmed?'fill-white':''}`})),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();const btn=e.currentTarget;setInstrumentDropdownTrackId(prev=>prev===track.id?null:track.id);setInstrumentDropdownBtnRect(btn.getBoundingClientRect());setInstrumentSearchQuery('');},title:track.instrumentName||track.instrumentId||"Synth",className:`px-1.5 py-0.5 text-[10px] rounded font-mono font-bold border transition flex items-center gap-0.5 max-w-[60px] ${track.instrumentId?'bg-violet-900 text-violet-300 border-violet-700':'bg-zinc-800 text-zinc-500 border-transparent hover:text-zinc-300'}`},/*#__PURE__*/React.createElement("i",{"data-lucide":"music",className:"w-3 h-3 shrink-0"}),/*#__PURE__*/React.createElement("span",{className:"truncate text-[9px]"},track.instrumentName||track.instrumentId||(instrumentDropdownTrackId===track.id?'':'Synth')),/*#__PURE__*/React.createElement("i",{"data-lucide":"chevron-down",className:"w-2.5 h-2.5 shrink-0"})),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackMonitor(track.id);},title:"Input Monitor",className:`px-1.5 py-0.5 text-[10px] rounded font-mono font-bold border transition flex items-center gap-0.5 ${track.monitoringEnabled?'bg-amber-600 text-white border-amber-500 hover:bg-amber-500':'bg-zinc-800 text-zinc-500 border-transparent hover:text-zinc-305'}`},/*#__PURE__*/React.createElement("i",{"data-lucide":track.monitoringEnabled?"mic":"mic-off",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();deleteTrack(track.id);},className:"p-0.5 rounded text-red-500 hover:bg-red-950/40 hover:text-red-400 transition"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"trash-2",className:"w-3 h-3"}))))),/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-0.5 text-xs",onClick:e=>e.stopPropagation()},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"w-8 text-right text-zinc-500 text-xs"},"Vol:"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-50",max:"7",step:"0.5",value:track.volumeDb??0,onChange:e=>updateTrackVolumeDb(track.id,parseFloat(e.target.value)),className:"flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-cyan-500",style:{height:'4px'}}),/*#__PURE__*/React.createElement("span",{className:"w-12 text-right font-mono text-zinc-300 text-xs"},track.volumeDb??0,"dB")),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"w-8 text-right text-zinc-500 text-xs"},"Pan:"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-100",max:"100",step:"1",value:track.pan??0,onChange:e=>updateTrackPan(track.id,parseInt(e.target.value)),className:"flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-purple-500",style:{height:'4px'}}),/*#__PURE__*/React.createElement("span",{className:"w-12 text-right font-mono text-zinc-300 text-xs"},track.pan>0?'R'+track.pan:track.pan<0?'L'+Math.abs(track.pan):'C')),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1 mt-0.5"},/*#__PURE__*/React.createElement("span",{className:"w-8 text-right text-zinc-500 text-[10px]"},"In:"),/*#__PURE__*/React.createElement("select",{value:`${track.inputSource?.deviceType||'NONE'}:${track.inputSource?.deviceId||''}`,onChange:e=>{const val=e.target.value;const parts=val.split(':');const type=parts[0];const id=parts.slice(1).join(':');updateTrackInputSource(track.id,type,id);},className:"flex-1 bg-[#18181b] text-zinc-300 text-[10px] rounded border border-zinc-700 focus:outline-none py-0.5 px-1 truncate max-w-[120px]"},/*#__PURE__*/React.createElement("option",{value:"NONE:"},"No Input"),/*#__PURE__*/React.createElement("optgroup",{label:"Microphones"},audioDevices.map(d=>/*#__PURE__*/React.createElement("option",{key:d.deviceId,value:`MICROPHONE:${d.deviceId}`},d.label||`Microphone ${d.deviceId.slice(0,5)}`))),/*#__PURE__*/React.createElement("optgroup",{label:"MIDI Keyboards"},/*#__PURE__*/React.createElement("option",{value:"MIDI_KEYBOARD:ALL"},"Any MIDI Keyboard"),midiDevices.map(d=>/*#__PURE__*/React.createElement("option",{key:d.id,value:`MIDI_KEYBOARD:${d.id}`},d.name||`MIDI Input ${d.id.slice(0,5)}`)))),track.isArmed&&lastMidiNote&&(lastMidiNote.length===0||Date.now()-lastMidiNote.time<3000)&&/*#__PURE__*/React.createElement("span",{className:"text-[9px] font-mono text-emerald-400 ml-0.5 truncate max-w-[60px] shrink-0",title:"MIDI Note:velocity:length"},`${midiPitchToName(lastMidiNote.pitch)}:${lastMidiNote.velocity}:${lastMidiNote.length>0?lastMidiNote.length.toFixed(2)+'s':'...'}`)),track.isArmed&&/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1 mt-0.5"},/*#__PURE__*/React.createElement("span",{className:"w-8 text-right text-zinc-500 text-[9px]"},"VU:"),/*#__PURE__*/React.createElement("canvas",{ref:el=>{if(el)trackVuRefs.current[track.id]=el;else delete trackVuRefs.current[track.id];},width:100,height:4,className:"flex-1 bg-[#18181b] rounded h-1"}))),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1.5 mt-1",onClick:e=>e.stopPropagation()},/*#__PURE__*/React.createElement("input",{type:"file",id:`upload-${track.id}`,accept:"audio/*",className:"hidden",onChange:e=>loadFileOnTrack(track.id,e.target.files[0])}),/*#__PURE__*/React.createElement("label",{htmlFor:`upload-${track.id}`,className:"px-2.5 py-1 bg-zinc-800 hover:bg-zinc-700 text-zinc-300 rounded text-xs flex items-center gap-1 cursor-pointer border border-zinc-700 font-medium"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"upload",className:"w-3 h-3"}))," File"),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();setFxSelectorTrackId(track.id);},className:"px-2.5 py-1 bg-zinc-800 hover:bg-zinc-700 text-purple-400 border border-purple-900 rounded text-xs font-bold flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"wand-2",className:"w-3 h-3"}))," FX: ",/*#__PURE__*/React.createElement("span",{className:"text-zinc-500 font-normal"},track.fxType||"None")),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();const btn=e.currentTarget;setInstrumentDropdownTrackId(prev=>prev===track.id?null:track.id);setInstrumentDropdownBtnRect(btn.getBoundingClientRect());setInstrumentSearchQuery('');},className:"px-2.5 py-1 bg-zinc-800 hover:bg-zinc-700 text-amber-400 border border-amber-800 rounded text-xs font-bold flex items-center gap-1 max-w-[120px]"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"music",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"truncate text-[10px]"},track.instrumentName||track.instrumentId||"Synth"),/*#__PURE__*/React.createElement("i",{"data-lucide":"chevron-down",className:"w-3 h-3 shrink-0"}))),/*#__PURE__*/React.createElement("div",{onMouseDown:e=>handleTrackResizeMouseDown(e,track.id),className:"absolute bottom-0 left-0 right-0 h-1 cursor-ns-resize z-30 hover:bg-cyan-500/50 transition-colors",onClick:e=>e.stopPropagation()}));})),/*#__PURE__*/React.createElement("div",{className:"h-[48px] border-r border-zinc-900 bg-[#1e1e1e]/50 shrink-0"})),/*#__PURE__*/React.createElement("div",{className:"w-1 cursor-ew-resize hover:bg-cyan-500/50 active:bg-cyan-400 transition-colors shrink-0 z-10",onMouseDown:startTcpResize}),/*#__PURE__*/React.createElement("div",{ref:handleTimelineWrapperRef,onScroll:handleTimelineScroll,className:"flex-1 relative z-10 overflow-x-auto overflow-y-auto min-w-0"},/*#__PURE__*/React.createElement("div",{style:{width:`${timelineWidth}px`},className:"relative flex flex-col min-h-full"},/*#__PURE__*/React.createElement(TimelineRuler,{bpm:parseInt(bpm)||120,zoom:zoom,timelineWidth:timelineWidth,viewportWidth:viewportWidth,onPlayheadSet:handlePlayheadSet,snapValue:snapValue,onRulerMouseDown:handleRulerMouseDown,scrollLeft:scrollLeft,canvasRedrawCount:canvasRedrawCount}),/*#__PURE__*/React.createElement(TempoTrackLane,{bpm:parseInt(bpm)||120,zoom:zoom,timelineWidth:timelineWidth,viewportWidth:viewportWidth,onPlayheadSet:handlePlayheadSet,snapValue:snapValue,onRulerMouseDown:handleRulerMouseDown,scrollLeft:scrollLeft,canvasRedrawCount:canvasRedrawCount}),selectionMode==='global'&&selLeft!==null&&selRight!==null&&selRight>selLeft&&/*#__PURE__*/React.createElement("div",{className:"absolute inset-0 pointer-events-none z-20",style:{left:`${selLeft*zoom}px`,width:`${(selRight-selLeft)*zoom}px`,top:'80px'}},/*#__PURE__*/React.createElement("div",{className:"w-full h-full bg-amber-500/10",style:{borderLeft:'1px solid #f59e0b',borderRight:'1px solid #f59e0b'}})),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col divide-y divide-[#141414] relative bg-[#111111] min-h-full"},activeTracks.map((track,idx)=>{const isSelected=selectedTrackId===track.id;const autoHeight=track.height||(track.isArmed?164:140);return/*#__PURE__*/React.createElement("div",{key:track.id,style:{height:`${autoHeight}px`},className:`shrink-0 relative border-b border-[#141414] hover:bg-zinc-850/5 transition-colors ${isSelected?'bg-zinc-800/10':''}`,onDragOver:e=>e.preventDefault(),onDrop:e=>{e.preventDefault();if(e.dataTransfer.files[0])loadFileOnTrack(track.id,e.dataTransfer.files[0]);},onMouseEnter:()=>setHoveredTrackId(track.id)},/*#__PURE__*/React.createElement(WaveformLane,{track:track,zoom:zoom,timelineWidth:timelineWidth,viewportWidth:viewportWidth,scrollLeft:scrollLeft,onSelectRange:handleSelectRange,onPlayheadSet:handlePlayheadSet,isSelected:isSelected,onSelectTrack:setSelectedTrackId,markers:track.markers,onTrackLaneMouseDown:handleTrackLaneMouseDown,onContextMenu:handleContextMenu,onClipDragStart:handleClipDragStart,onClipStretchStart:handleClipStretchStart,onSectionItemDragStart:handleSectionItemDragStart,onSectionItemResizeStart:handleSectionItemResizeStart,onSelectionEdgeDragStart:handleSelectionEdgeDragStart,setSelectedClipId:setSelectedClipId,selectedClipId:selectedClipId,activeTool:activeTool,onSplitTrackAtTime:handleSplitTrackAtTime,onEditClipInSubTab:handleEditClipInSubTab,onEditSectionInTab:handleEditSectionInTab,onEditMidiInTab:handleEditMidiInTab,snapValue:snapValue,bpm:bpm,selectionMode:selectionMode,localSelectionTrackId:localSelectionTrackId,localSelectionStart:localSelectionStart,currentTime:currentTime,getLocalAnchor:()=>localSelectionAnchorRef.current,onClearLocalSelection:clearLocalSelection,onSetSelectionMode:setSelectionMode,onSetSelectionStart:setSelectionStart,onSetSelectionEnd:setSelectionEnd,onSetCurrentTime:setCurrentTime,onSetLocalSelectionTrackId:setLocalSelectionTrackId,onSetLocalSelectionStart:setLocalSelectionStart,onSetLocalSelectionEnd:setLocalSelectionEnd,localSelLeft:localSelectionStart!==null&&localSelectionEnd!==null?Math.min(localSelectionStart,localSelectionEnd):null,localSelRight:localSelectionStart!==null&&localSelectionEnd!==null?Math.max(localSelectionStart,localSelectionEnd):null,scrollLeft:scrollLeft,recordingState:recordingState,recTempMidiNotes:recTempMidiNotes,recTempAudioBuffer:recTempAudioBuffer,recStartTimelineTime:recStartTimelineTime,canvasRedrawCount:canvasRedrawCount}),selectionMode==='local'&&localSelectionTrackId===track.id&&localSelectionStart!==null&&localSelectionEnd!==null&&Math.abs(localSelectionEnd-localSelectionStart)>0&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 border-l border-r border-amber-400 bg-amber-500/20 z-20 pointer-events-none",style:{left:`${Math.min(localSelectionStart,localSelectionEnd)*zoom}px`,width:`${Math.abs(localSelectionEnd-localSelectionStart)*zoom}px`}},/*#__PURE__*/React.createElement("div",{className:"absolute -left-[1px] top-0 bottom-0 w-[2px] bg-amber-400 z-30 pointer-events-auto cursor-ew-resize",onMouseDown:e=>handleHandleDragStart(e,'left')}),/*#__PURE__*/React.createElement("div",{className:"absolute -right-[1px] top-0 bottom-0 w-[2px] bg-amber-400 z-30 pointer-events-auto cursor-ew-resize",onMouseDown:e=>handleHandleDragStart(e,'right')})),track.buffer&&/*#__PURE__*/React.createElement("div",{className:"absolute right-2 top-2 flex items-center gap-1 z-10 opacity-70 hover:opacity-100"},/*#__PURE__*/React.createElement("button",{onClick:()=>handleSplitTrack(track.id),className:"px-1.5 py-0.5 bg-zinc-900/95 text-zinc-300 rounded text-xs flex items-center gap-1 border border-zinc-700/50"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-2.5 h-2.5 text-cyan-400"}))," Cắt")),/*#__PURE__*/React.createElement("div",{onMouseDown:e=>handleTrackResizeMouseDown(e,track.id),className:"absolute bottom-0 left-0 right-0 h-1 cursor-ns-resize z-30 hover:bg-cyan-500/50 transition-colors",onClick:e=>e.stopPropagation()}));}),/*#__PURE__*/React.createElement("div",{className:"h-[48px] flex items-center justify-center text-xs text-zinc-500 hover:bg-zinc-900/20 cursor-pointer select-none border-t border-dashed border-zinc-800",onMouseEnter:()=>{if(draggedClipRef.current||draggedSectionItemRef.current){setHoveredTrackId(addNewTrack());}},onClick:addNewTrack},/*#__PURE__*/React.createElement("span",{className:"flex items-center gap-1 text-zinc-400"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus",className:"w-3.5 h-3.5"}))," Kéo clip xuống hoặc Click tạo Track")),selectionMode==='global'&&selLeft!==null&&selRight!==null&&selRight>selLeft&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 border-l border-r border-amber-500 bg-amber-500/10 z-20 selection-interactive-box cursor-grab active:cursor-grabbing",style:{left:`${selLeft*zoom}px`,width:`${(selRight-selLeft)*zoom}px`},onMouseDown:handleSelectionBodyDragStart},/*#__PURE__*/React.createElement("div",{className:"absolute -left-[1px] top-0 bottom-0 w-[1px] bg-amber-500 hover:bg-amber-400 cursor-ew-resize z-30",onMouseDown:e=>handleHandleDragStart(e,'left')}),/*#__PURE__*/React.createElement("div",{className:"absolute -right-[1px] top-0 bottom-0 w-[1px] bg-amber-500 hover:bg-amber-400 cursor-ew-resize z-30",onMouseDown:e=>handleHandleDragStart(e,'right')})),/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 w-[2px] bg-[#ef4444] z-20 pointer-events-none",style:{left:`${playheadLeftPos}px`}},/*#__PURE__*/React.createElement("div",{className:"w-3 h-3 bg-[#ef4444] rotate-45 transform -translate-x-1/2 -translate-y-1/2 absolute top-0"})))))):(()=>{const st=subTabs.find(s=>s.id===activeTab);if(!st)return null;if(st.type==='PIANO_ROLL'){return/*#__PURE__*/React.createElement(PianoRollTabEditor,{st:st,zoom:zoom,bpm:bpm,viewportWidth:viewportWidth,onClose:()=>closeSubTab(st.id),onUpdateNotes:handleUpdateMidiNotes,onSaveNotes:handleSaveMidiNotes,setSubTabs:setSubTabs,onPlayPause:handlePlayPause,onStop:stopAllPlayback,isPlaying:isPlaying,playPreviewNote:playMidiPreviewNote,showToast:showToast,midiDevices:midiDevices,recordingState:recordingState,recTempMidiNotes:recTempMidiNotes,onRecord:handleRecordClick,selectedMidiInputId:selectedMidiInputId,onMidiInputSelect:handleMidiInputSelect,activeMidiPitches:activeMidiPitches,onInstrumentSelect:trackId=>{openInstrumentSelector(trackId);},onRescheduleMidi:updatedNotes=>{const playingSub=subTabs.find(s=>s.id===activeTab&&s.type==='PIANO_ROLL'&&s.isPlaying);if(playingSub){const offset=playingSub.currentTime||0;window.SonicSF.stopAll();setTimeout(()=>{const ctx=getAudioContext();startOffsetTimeRef.current=offset;startAudioTimeRef.current=ctx.currentTime;startBufferOffsetRef.current=offset*(playingSub.speed||1.0);schedulePianoRollMidi(playingSub,offset,updatedNotes);},20);}}});}const subTrack=tracks.find(t=>t.id===st.trackId);const vTrack=subTrack?{...subTrack,buffer:st.buffer,isSubTab:true}:null;const subTabDuration=st.type==='PIANO_ROLL'?(()=>{const notes=st.notes||[];const beatSec=60.0/(parseFloat(bpm)||120);let maxEnd=0;notes.forEach(n=>{const end=(n.start_beat||0)+(n.duration_beats||1);if(end>maxEnd)maxEnd=end;});return maxEnd*beatSec+1.0;})():st.buffer&&'duration'in st.buffer?st.buffer.duration:4.0;const subTabTimelineWidth=Math.max(zoom*subTabDuration,viewportWidth);return/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{className:"shrink-0 z-30 bg-[#262626] overflow-y-scroll no-scrollbar flex flex-col border-r border-zinc-900",style:{width:tcpWidth+'px',scrollbarWidth:'none',msOverflowStyle:'none'}},/*#__PURE__*/React.createElement("div",{className:"sticky top-0 z-50 flex items-center h-10 border-b border-zinc-900 bg-[#242424] px-2 justify-between shrink-0"},/*#__PURE__*/React.createElement("span",{className:"text-xs font-bold text-zinc-500 uppercase"},"Sub-Tab"),/*#__PURE__*/React.createElement("button",{onClick:()=>closeSubTab(st.id),className:"px-1.5 py-0.5 text-xs bg-zinc-800 hover:bg-zinc-700 text-zinc-400 rounded border border-zinc-700 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"}))," Close")),vTrack?/*#__PURE__*/React.createElement("div",{key:vTrack.id,className:"flex-1 flex flex-col p-2.5 bg-[#1e1e1e] border-r border-zinc-900 border-l-4 border-l-cyan-500"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between mb-2"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2"},/*#__PURE__*/React.createElement("label",{onClick:e=>{e.stopPropagation();const el=e.currentTarget.querySelector('input');if(el)el.click();},className:"cursor-pointer"},/*#__PURE__*/React.createElement("input",{type:"color",value:vTrack.color||'#0f766e',onChange:e=>{e.stopPropagation();updateTrackColor(vTrack.id,e.target.value);},className:"w-0 h-0 opacity-0 absolute pointer-events-none"}),/*#__PURE__*/React.createElement("div",{className:"w-3 h-3 rounded-full border border-zinc-600 hover:scale-110 transition-transform",style:{backgroundColor:vTrack.color}})),editingTrackName===vTrack.id?/*#__PURE__*/React.createElement("input",{type:"text",value:editNameInput,autoFocus:true,onChange:e=>setEditNameInput(e.target.value),onBlur:()=>{updateTrackName(vTrack.id,editNameInput||vTrack.name);setEditingTrackName(null);},onKeyDown:e=>{if(e.key==='Enter'){updateTrackName(vTrack.id,editNameInput||vTrack.name);setEditingTrackName(null);}if(e.key==='Escape')setEditingTrackName(null);},onClick:e=>e.stopPropagation(),className:"text-xs font-semibold bg-black text-zinc-200 border border-cyan-500 rounded px-1 py-0 w-24 outline-none"}):/*#__PURE__*/React.createElement("span",{className:"text-xs font-semibold text-zinc-300 truncate max-w-[80px] cursor-text hover:text-cyan-300 transition-colors",title:"Click to rename",onClick:e=>{e.stopPropagation();setEditingTrackName(vTrack.id);setEditNameInput(vTrack.name);}},vTrack.name)),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackMute(vTrack.id);},className:`px-1.5 py-0.5 text-xs rounded font-mono font-bold border ${vTrack.muted?'bg-red-950 text-red-400 border-red-700':'bg-zinc-800 text-zinc-400 border-transparent hover:text-zinc-200'}`},"M"),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackSoloEvaluate(vTrack.id);},className:`px-1.5 py-0.5 text-xs rounded font-mono font-bold border ${soloedTrackId===vTrack.id||vTrack.solo?'bg-amber-950 text-amber-400 border-amber-600':'bg-zinc-800 text-zinc-400 border-transparent hover:text-zinc-200'}`},"S"))),/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-2.5 text-[14px] mb-3"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"w-10 text-right text-zinc-500 text-[14px]"},"Vol:"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-50",max:"7",step:"0.5",id:`tcp-vol-${st.id}`,value:vTrack.volumeDb??0,onChange:e=>updateTrackVolumeDb(vTrack.id,parseFloat(e.target.value)),className:"flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-cyan-500",style:{height:'4px'}}),/*#__PURE__*/React.createElement("span",{className:"w-16 text-right font-mono text-zinc-300 text-[14px]",id:`tcp-vol-label-${st.id}`},vTrack.volumeDb??0,"dB")),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"w-10 text-right text-zinc-500 text-[14px]"},"Pan:"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-100",max:"100",step:"1",id:`tcp-pan-${st.id}`,value:vTrack.pan??0,onChange:e=>updateTrackPan(vTrack.id,parseInt(e.target.value)),className:"flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-purple-500",style:{height:'4px'}}),/*#__PURE__*/React.createElement("span",{className:"w-16 text-right font-mono text-zinc-300 text-[14px]",id:`tcp-pan-label-detailed-${st.id}`},vTrack.pan>0?'R'+vTrack.pan:vTrack.pan<0?'L'+Math.abs(vTrack.pan):'C')),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1.5 text-[14px]"},/*#__PURE__*/React.createElement("button",{onClick:()=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,isLooping:!s.isLooping}:s)),className:`px-2 py-0.5 text-[14px] rounded border font-bold ${st.isLooping?'bg-amber-700 text-white border-amber-500':'bg-zinc-800 text-zinc-400 border-zinc-700'}`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"repeat",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>updateSubTabEffects(st.id,{reverse:!(st.effects||{}).reverse}),className:`px-2 py-0.5 rounded border text-[14px] font-bold ${(st.effects||{}).reverse?'bg-zinc-600 text-white border-zinc-500':'bg-zinc-800 text-zinc-400 border-zinc-700'} flex items-center justify-center`,title:"Reverse"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"arrow-left-right",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("span",{className:"w-10 text-right text-zinc-500 text-[14px]"},"Loop:"),/*#__PURE__*/React.createElement("input",{type:"number",min:"0",max:"999",value:st.loopCount||0,onChange:e=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,loopCount:Math.max(0,parseInt(e.target.value)||0)}:s)),className:"w-12 bg-black text-amber-300 text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono",title:"Loop count"}))),/*#__PURE__*/React.createElement("div",{className:"flex gap-1 justify-between my-2.5"},/*#__PURE__*/React.createElement("div",{className:"flex flex-col items-center bg-zinc-900/60 p-1.5 rounded border border-zinc-800 flex-1"},/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-bold text-zinc-400 uppercase tracking-tighter",title:"Normalize"},"Norm"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-12",max:"0",step:"0.1",value:subTabNormVal,onChange:e=>setSubTabNormVal(parseFloat(e.target.value)),style:{writingMode:'vertical-lr',direction:'rtl',height:'120px',width:'20px',accentColor:'#a1a1aa'},className:"my-2 cursor-pointer"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-mono text-zinc-300 font-bold"},subTabNormVal,"dB"),/*#__PURE__*/React.createElement("button",{onClick:()=>applySubTabEffect(st.id,'normalize',subTabNormVal),className:"mt-1.5 px-1 py-1 bg-zinc-700 hover:bg-zinc-600 text-zinc-100 rounded text-[14px] font-bold w-full uppercase border border-zinc-650"},"Apply")),/*#__PURE__*/React.createElement("div",{className:"flex flex-col items-center bg-zinc-900/60 p-1.5 rounded border border-zinc-800 flex-1"},/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-bold text-zinc-400 uppercase tracking-tighter",title:"Pitch Shift"},"Pitch"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-12",max:"12",step:"0.5",value:subTabPitchVal,onChange:e=>setSubTabPitchVal(parseFloat(e.target.value)),style:{writingMode:'vertical-lr',direction:'rtl',height:'120px',width:'20px',accentColor:'#a1a1aa'},className:"my-2 cursor-pointer"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-mono text-zinc-300 font-bold"},subTabPitchVal>0?'+':'',subTabPitchVal,"st"),/*#__PURE__*/React.createElement("button",{onClick:()=>applySubTabEffect(st.id,'pitch',subTabPitchVal),className:"mt-1.5 px-1 py-1 bg-zinc-700 hover:bg-zinc-600 text-zinc-100 rounded text-[14px] font-bold w-full uppercase border border-zinc-650"},"Apply")),/*#__PURE__*/React.createElement("div",{className:"flex flex-col items-center bg-zinc-900/60 p-1.5 rounded border border-zinc-800 flex-1"},/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-bold text-zinc-400 uppercase tracking-tighter",title:"Gain Multiplier"},"Gain"),/*#__PURE__*/React.createElement("input",{type:"range",min:"0",max:"150",step:"1",value:subTabGainVal,onChange:e=>setSubTabGainVal(parseInt(e.target.value)),style:{writingMode:'vertical-lr',direction:'rtl',height:'120px',width:'20px',accentColor:'#a1a1aa'},className:"my-2 cursor-pointer"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-mono text-zinc-300 font-bold"},subTabGainVal,"%"),/*#__PURE__*/React.createElement("button",{onClick:()=>applySubTabEffect(st.id,'gain',subTabGainVal),className:"mt-1.5 px-1 py-1 bg-zinc-700 hover:bg-zinc-600 text-zinc-100 rounded text-[14px] font-bold w-full uppercase border border-zinc-650"},"Apply"))),/*#__PURE__*/React.createElement("div",{className:"flex-1"}),/*#__PURE__*/React.createElement("div",{className:"mt-auto pt-2.5 border-t border-zinc-800"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between text-[14px] text-zinc-500 mb-1 font-semibold uppercase"},/*#__PURE__*/React.createElement("span",null,"Duration:"),/*#__PURE__*/React.createElement("span",{className:"font-mono text-zinc-300"},st.buffer?formatTime(subTabDuration):'0s')),/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between text-[14px] text-zinc-500 mb-2.5 font-semibold uppercase"},/*#__PURE__*/React.createElement("span",null,"SR:"),/*#__PURE__*/React.createElement("span",{className:"font-mono text-zinc-300"},st.buffer?st.buffer.sampleRate:0," Hz")),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1 mb-2"},/*#__PURE__*/React.createElement("button",{onClick:async e=>{subTabAiTrackIdRef.current=st.trackId;handleAIScan();},disabled:analysisState.isRunning,className:"py-1 bg-purple-900 hover:bg-purple-800 text-purple-100 font-bold rounded text-xs border border-purple-700 flex items-center justify-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"map-pin",className:"w-3 h-3"}))," Scan"),/*#__PURE__*/React.createElement("button",{onClick:async e=>{subTabAiTrackIdRef.current=st.trackId;handleAICutToNewTrack();},disabled:analysisState.isRunning,className:"py-1 bg-fuchsia-800 hover:bg-fuchsia-700 text-white font-bold rounded text-xs flex items-center justify-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-3 h-3"}))," Cut"),/*#__PURE__*/React.createElement("button",{onClick:async e=>{subTabAiTrackIdRef.current=st.trackId;if(st.buffer){setSelectionRangeOnBuffer(st.buffer,st.selectionStart||0,st.selectionEnd||st.buffer.duration);}handleAIAnalysicLoop();},disabled:analysisState.isRunning,className:"py-1 bg-violet-800 hover:bg-violet-700 text-violet-100 font-bold rounded text-xs border border-violet-600 flex items-center justify-center gap-1 col-span-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sparkles",className:"w-3 h-3"}))," AI Analysic Loop")),/*#__PURE__*/React.createElement("button",{onClick:()=>exportSubTabBuffer(st.id),className:"w-full py-1.5 mb-1.5 bg-blue-700 hover:bg-blue-600 text-white font-bold rounded text-[14px] flex items-center justify-center gap-1 transition"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"download",className:"w-4 h-4"}))," Export"),/*#__PURE__*/React.createElement("button",{onClick:()=>applySubTab(st.id),className:"w-full py-1.5 bg-emerald-700 hover:bg-emerald-600 text-white font-bold rounded text-[14px] flex items-center justify-center gap-1 transition"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"save",className:"w-4 h-4"}))," Save"))):/*#__PURE__*/React.createElement("div",{className:"flex-1 flex items-center justify-center text-xs text-zinc-500"},"Track not found")),/*#__PURE__*/React.createElement("div",{className:"w-1 cursor-ew-resize hover:bg-cyan-500/50 active:bg-cyan-400 transition-colors shrink-0 z-10",onMouseDown:startTcpResize}),/*#__PURE__*/React.createElement("div",{ref:handleTimelineWrapperRef,className:"flex-1 relative z-10 overflow-x-auto overflow-y-auto min-w-0"},/*#__PURE__*/React.createElement("div",{style:{width:`${subTabTimelineWidth}px`},className:"relative flex flex-col min-h-full"},/*#__PURE__*/React.createElement(TimelineRuler,{bpm:parseInt(bpm)||120,zoom:zoom,timelineWidth:subTabTimelineWidth,viewportWidth:viewportWidth,onPlayheadSet:setCurrentTime,snapValue:snapValue,onRulerMouseDown:e=>{const wrapper=timelineWrapperRef.current;if(!wrapper)return;const rect=wrapper.getBoundingClientRect();const sl=wrapper.scrollLeft;const raw=Math.max(0,(e.clientX-rect.left+sl)/zoom);const t=snapValue!=='free'?snapTime(raw,snapValue,bpm):raw;if(e.shiftKey){e.preventDefault();e.stopPropagation();}handlePlayheadSet(t);},scrollLeft:scrollLeft,canvasRedrawCount:canvasRedrawCount}),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col relative bg-[#111111] min-h-full"},vTrack&&/*#__PURE__*/React.createElement("div",{style:{height:`${subTabHeight}px`},className:"relative overflow-hidden border-2 border-purple-500/40 rounded bg-[#151515] mx-1 mt-1 shrink-0"},/*#__PURE__*/React.createElement(SubTabWaveform,{buffer:st.buffer,subTabId:st.id,activeTab:activeTab,activeTool:activeTool,currentTime:st.currentTime,selectionStart:st.selectionStart,selectionEnd:st.selectionEnd,onSelectRange:(start,end)=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,selectionStart:start,selectionEnd:end}:s)),onPlayheadSet:time=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,currentTime:time}:s)),onContextMenu:(e,clickTime)=>setContextMenu({x:e.clientX,y:e.clientY,isSubTab:true,subTabId:st.id,time:clickTime}),zoom:zoom,timelineWidth:subTabTimelineWidth,color:vTrack.color,name:vTrack.name,speed:st.speed||1.0,volumeNodes:st.volumeNodes||[],panningNodes:st.panningNodes||[],fadeInLen:st.fadeInLen||0,fadeOutLen:st.fadeOutLen||0,graphMode:st.graphMode,channelInfo:st.channelInfo,selectedNodeTime:subTabSelectedNodeTime,setSelectedNodeTime:setSubTabSelectedNodeTime,onUpdateNodes:nodes=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,[s.graphMode==='pan'?'panningNodes':'volumeNodes']:nodes}:s)),onUpdateFade:fade=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,fadeInLen:fade.fadeInLen??s.fadeInLen,fadeOutLen:fade.fadeOutLen??s.fadeOutLen}:s)),onModeToggle:()=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,graphMode:s.graphMode==='pan'?null:'pan'}:s)),onSpeedChange:newSpeed=>{setSubTabs(prev=>prev.map(s=>{if(s.id!==st.id)return s;const oldSpeed=s.speed||1.0;const ratio=oldSpeed/newSpeed;const newVolumeNodes=(s.volumeNodes||[]).map(n=>({...n,time:n.time*ratio}));const newPanningNodes=(s.panningNodes||[]).map(n=>({...n,time:n.time*ratio}));return{...s,speed:newSpeed,volumeNodes:newVolumeNodes,panningNodes:newPanningNodes,fadeInLen:(s.fadeInLen||0)*ratio,fadeOutLen:(s.fadeOutLen||0)*ratio,currentTime:(s.currentTime||0)*ratio,label:s.label.replace(/\s\(\d+%\)$/,'')+` (${Math.round(newSpeed*100)}%)`};}));const n=activeTrackNodesRef.current[st.trackId];if(n&&n.source)n.source.playbackRate.value=newSpeed;// Reset time refs to prevent playhead jump when speed changes mid-playback const ctx=getAudioContext();const elapsed=ctx.currentTime-startAudioTimeRef.current;const oldSpeed=activePlaybackSpeedRef.current;const ratio=oldSpeed/newSpeed;startBufferOffsetRef.current=startBufferOffsetRef.current+elapsed*oldSpeed;startOffsetTimeRef.current=(startOffsetTimeRef.current+elapsed)*ratio;startAudioTimeRef.current=ctx.currentTime;activePlaybackSpeedRef.current=newSpeed;}}),/*#__PURE__*/React.createElement("div",{onMouseDown:handleSubTabResizeMouseDown,className:"absolute bottom-0 left-0 right-0 h-1.5 cursor-ns-resize z-30 hover:bg-purple-500/50 transition-colors"})),st.selectionStart!==null&&st.selectionEnd!==null&&st.selectionEnd>st.selectionStart&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 border-l border-r border-amber-500 bg-amber-500/10 z-20 pointer-events-none",style:{left:`${Math.min(st.selectionStart,st.selectionEnd)*zoom}px`,width:`${Math.abs(st.selectionEnd-st.selectionStart)*zoom}px`}})))));})())),/*#__PURE__*/React.createElement("div",{className:"w-1 cursor-ew-resize hover:bg-cyan-500/50 active:bg-cyan-400 transition-colors shrink-0 z-10",onMouseDown:startColResize}),renderDock('right','Right')),renderDock('bottom','Bottom'));})(),/*#__PURE__*/React.createElement("div",{className:"h-6 bg-[#141414] border-t border-zinc-900 px-4 flex items-center justify-between text-xs text-zinc-500 select-none shrink-0"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-4"},/*#__PURE__*/React.createElement("span",null,"Status: ",isPlaying?'Playing':'Stopped'),activeTab!=='main'&&/*#__PURE__*/React.createElement("span",{className:"text-amber-400 font-semibold uppercase"},"Sub-Tab"),activeTab==='main'&&/*#__PURE__*/React.createElement("span",{className:"text-cyan-400 font-semibold uppercase"},"Track: ID ",selectedTrackId),selectionMode==='local'&&/*#__PURE__*/React.createElement("span",{className:"text-amber-400 font-semibold uppercase text-xs"},"Local Sel"),selectionMode==='global'&&/*#__PURE__*/React.createElement("span",{className:"text-purple-400 font-semibold uppercase text-xs"},"Global Sel"),soloedTrackId&&/*#__PURE__*/React.createElement("span",{className:"text-amber-500 font-semibold"},"Solo: ID ",soloedTrackId),isLoopingSelection&&selectionMode==='local'&&/*#__PURE__*/React.createElement("span",{className:"text-emerald-400 font-semibold uppercase text-xs"},"Solo Loop"),isLoopingSelection&&selectionMode!=='local'&&/*#__PURE__*/React.createElement("span",{className:"text-cyan-400 font-semibold uppercase text-xs"},"Master Loop")),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2"},/*#__PURE__*/React.createElement("button",{onClick:()=>setShowExportPanel(p=>!p),className:`px-1.5 py-0.5 rounded text-xs font-semibold transition flex items-center gap-1 ${showExportPanel?'bg-cyan-900 text-cyan-300':'text-zinc-500 hover:text-zinc-300'}`,title:`Export Panel (${panelPositions.export})`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"save",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"text-[7px] opacity-60"},showExportPanel?panelPositions.export[0].toUpperCase():'')),/*#__PURE__*/React.createElement("button",{onClick:()=>setShowSelectionPanel(p=>!p),className:`px-1.5 py-0.5 rounded text-xs font-semibold transition flex items-center gap-1 ${showSelectionPanel?'bg-amber-900 text-amber-300':'text-zinc-500 hover:text-zinc-300'}`,title:`Selection Panel (${panelPositions.selection})`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sliders",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"text-[7px] opacity-60"},showSelectionPanel?panelPositions.selection[0].toUpperCase():'')),/*#__PURE__*/React.createElement("button",{onClick:()=>setShowAIPanel(p=>!p),className:`px-1.5 py-0.5 rounded text-xs font-semibold transition flex items-center gap-1 ${showAIPanel?'bg-purple-900 text-purple-300':'text-zinc-500 hover:text-zinc-300'}`,title:`AI Panel (${panelPositions.ai})`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"cpu",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"text-[7px] opacity-60"},showAIPanel?panelPositions.ai[0].toUpperCase():'')),/*#__PURE__*/React.createElement("button",{onClick:()=>setShowFxRack(p=>!p),className:`px-1.5 py-0.5 rounded text-xs font-semibold transition flex items-center gap-1 ${showFxRack?'bg-rose-900 text-rose-300':'text-zinc-500 hover:text-zinc-300'}`,title:`FX Rack Panel (${panelPositions.fx_rack||'bottom'})`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sliders",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"text-[7px] opacity-60"},showFxRack?(panelPositions.fx_rack||'bottom')[0].toUpperCase():'')),/*#__PURE__*/React.createElement("button",{onClick:()=>setShowMidiEvents(p=>!p),className:`px-1.5 py-0.5 rounded text-xs font-semibold transition flex items-center gap-1 ${showMidiEvents?'bg-sky-900 text-sky-300':'text-zinc-500 hover:text-zinc-300'}`,title:`MIDI Events Panel (${panelPositions.midi_events||'bottom'})`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"music",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"text-[7px] opacity-60"},showMidiEvents?(panelPositions.midi_events||'bottom')[0].toUpperCase():'')),/*#__PURE__*/React.createElement("span",{className:"w-[1px] h-3 bg-zinc-800 mx-1"}),/*#__PURE__*/React.createElement("span",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"info",className:"w-3 h-3 text-zinc-600"}))," Scroll: Zoom"),/*#__PURE__*/React.createElement("span",null,"|"),/*#__PURE__*/React.createElement("span",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"keyboard",className:"w-3 h-3 text-zinc-600"}))," Ctrl+Scroll: Playhead"))),contextMenu&&(contextMenu.isSubTab?/*#__PURE__*/React.createElement("div",{className:"fixed z-[60] bg-[#2a2a2a] border border-zinc-700 rounded-lg shadow-2xl py-1 w-64",style:{left:contextMenu.x,top:contextMenu.y},onClick:e=>e.stopPropagation()},/*#__PURE__*/React.createElement("div",{className:"px-3 py-1 text-xs text-zinc-500 font-bold uppercase border-b border-zinc-800 pb-1 mb-1"},"Selection: ",formatTime(subTabs.find(s=>s.id===contextMenu.subTabId)?.selectionStart||0)," - ",formatTime(subTabs.find(s=>s.id===contextMenu.subTabId)?.selectionEnd||0)),/*#__PURE__*/React.createElement("div",{className:"h-px bg-zinc-700 my-1"}),/*#__PURE__*/React.createElement("button",{onClick:()=>{handleSubTabCut(contextMenu.subTabId);closeContextMenu();},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-3.5 h-3.5 text-rose-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Cut"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto"},"Ctrl+X")),/*#__PURE__*/React.createElement("button",{onClick:()=>{handleSubTabCopy(contextMenu.subTabId);closeContextMenu();},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"copy",className:"w-3.5 h-3.5 text-zinc-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Copy"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto"},"Ctrl+C")),/*#__PURE__*/React.createElement("button",{onClick:()=>{handleSubTabPaste(contextMenu.subTabId);closeContextMenu();},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"clipboard",className:"w-3.5 h-3.5 text-emerald-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Paste"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto"},"Ctrl+V")),/*#__PURE__*/React.createElement("button",{onClick:()=>{handleSubTabDelete(contextMenu.subTabId);closeContextMenu();},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"trash-2",className:"w-3.5 h-3.5 text-red-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Delete Selected Segment"),/*#__PURE__*/React.createElement("span",{className:"text-amber-400 text-xs font-semibold font-mono ml-auto"},"Del")),/*#__PURE__*/React.createElement("div",{className:"h-px bg-zinc-700 my-1"}),/*#__PURE__*/React.createElement("button",{onClick:()=>{handleSubTabLoop(contextMenu.subTabId,4);closeContextMenu();},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"repeat",className:"w-3.5 h-3.5 text-cyan-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Loop Selection 4 times"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto"},"Ctrl+L"))):/*#__PURE__*/React.createElement("div",{className:"fixed z-[60] bg-[#2a2a2a] border border-zinc-700 rounded-lg shadow-2xl py-1 w-64",style:{left:contextMenu.x,top:contextMenu.y},onClick:e=>e.stopPropagation()},contextMenu.sectionId?/*#__PURE__*/React.createElement("button",{onClick:contextMenuEditSection,className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"file-edit",className:"w-3.5 h-3.5 text-amber-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Edit Section"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},"Ctrl+E")):/*#__PURE__*/React.createElement("button",{onClick:contextMenuEdit,className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"file-edit",className:"w-3.5 h-3.5 text-amber-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Edit"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},"Ctrl+E")),/*#__PURE__*/React.createElement("button",{onClick:contextMenuSplit,className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-3.5 h-3.5 text-cyan-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Split"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},"S")),/*#__PURE__*/React.createElement("button",{onClick:contextMenuMerge,className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"combine",className:"w-3.5 h-3.5 text-purple-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Merge"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},"Ctrl+M")),/*#__PURE__*/React.createElement("div",{className:"h-px bg-zinc-700 my-1"}),/*#__PURE__*/React.createElement("div",{className:"px-3 py-0.5 text-[10px] text-zinc-500 font-bold uppercase tracking-wider"},"Insert"),/*#__PURE__*/React.createElement("button",{onClick:()=>{insertSectionAtPlayhead();closeContextMenu();},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"folder-plus",className:"w-3.5 h-3.5 text-amber-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Insert Section")),/*#__PURE__*/React.createElement("button",{onClick:()=>{insertMidiItemAtPlayhead();closeContextMenu();},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"music",className:"w-3.5 h-3.5 text-purple-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Insert MIDI Item")),/*#__PURE__*/React.createElement("button",{onClick:()=>{insertSoundClipAtCursor();closeContextMenu();},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"file-audio",className:"w-3.5 h-3.5 text-emerald-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Insert Sound Clip")),/*#__PURE__*/React.createElement("button",{onClick:()=>{insertTrackBelow();closeContextMenu();},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus-square",className:"w-3.5 h-3.5 text-cyan-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Insert Track")),/*#__PURE__*/React.createElement("div",{className:"h-px bg-zinc-700 my-1"}),/*#__PURE__*/React.createElement("button",{onClick:contextMenuCopy,className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"copy",className:"w-3.5 h-3.5 text-zinc-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Copy"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},"Ctrl+C")),/*#__PURE__*/React.createElement("button",{onClick:contextMenuCut,className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-3.5 h-3.5 text-rose-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Cut"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},"Ctrl+X")),/*#__PURE__*/React.createElement("button",{onClick:contextMenuPaste,className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"clipboard",className:"w-3.5 h-3.5 text-emerald-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Paste"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},"Ctrl+V")),/*#__PURE__*/React.createElement("div",{className:"h-px bg-zinc-700 my-1"}),/*#__PURE__*/React.createElement("button",{onClick:contextMenuDelete,className:"w-full px-3 py-1.5 text-xs text-red-300 hover:bg-red-950 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"trash-2",className:"w-3.5 h-3.5 text-red-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Delete"),/*#__PURE__*/React.createElement("span",{className:"text-amber-400 text-xs font-semibold font-mono ml-auto pl-8"},"Del")))),toastMessage&&/*#__PURE__*/React.createElement("div",{className:"absolute top-14 right-4 z-50 px-4 py-2.5 rounded shadow-lg text-xs font-semibold flex items-center gap-2 border bg-zinc-900 text-zinc-100 border-zinc-800"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"bell",className:`w-4 h-4 ${toastMessage.type==='success'?'text-emerald-400':toastMessage.type==='error'?'text-rose-400':toastMessage.type==='warning'?'text-amber-400':'text-cyan-400'}`})),toastMessage.text,toastMessage.onActionClick&&/*#__PURE__*/React.createElement("button",{onClick:()=>{toastMessage.onActionClick();setToastMessage(null);},className:"ml-2 px-2 py-0.5 bg-purple-700 hover:bg-purple-600 text-white rounded text-[10px] uppercase font-bold"},toastMessage.actionText||'Tải về'))),appWarningModal&&/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-[100] flex items-center justify-center bg-black/60 backdrop-blur-sm"},/*#__PURE__*/React.createElement("div",{className:"bg-[#222222] border border-zinc-800 rounded-lg shadow-2xl p-6 max-w-md w-full text-slate-200"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2 mb-3 text-cyan-400 font-bold"},/*#__PURE__*/React.createElement("h3",{className:"text-base font-bold"},appWarningModal.title)),/*#__PURE__*/React.createElement("div",{className:"text-xs text-slate-300 mb-5 leading-relaxed whitespace-pre-line"},appWarningModal.message),/*#__PURE__*/React.createElement("div",{className:"flex justify-end gap-2"},appWarningModal.isAlert?/*#__PURE__*/React.createElement("button",{onClick:()=>setAppWarningModal(null),className:"px-4 py-2 bg-cyan-600 hover:bg-cyan-500 active:bg-cyan-700 text-white rounded text-xs font-semibold transition"},"Đóng"):/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("button",{onClick:()=>setAppWarningModal(null),className:"px-4 py-2 bg-zinc-700 hover:bg-zinc-600 active:bg-zinc-800 text-slate-300 rounded text-xs font-semibold transition"},"Hủy"),/*#__PURE__*/React.createElement("button",{onClick:()=>{const fn=appWarningModal.onConfirm;setAppWarningModal(null);if(fn)fn();},className:"px-4 py-2 bg-cyan-600 hover:bg-cyan-500 active:bg-cyan-700 text-white rounded text-xs font-semibold transition"},"Xác nhận"))))),tabContextMenu&&/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-[190]",onClick:()=>setTabContextMenu(null),onContextMenu:e=>{e.preventDefault();setTabContextMenu(null);}}),/*#__PURE__*/React.createElement("div",{className:"fixed bg-zinc-900 border border-zinc-800 rounded-lg shadow-2xl p-2 z-[200] flex gap-1.5",style:{top:tabContextMenu.y,left:tabContextMenu.x},onClick:e=>e.stopPropagation()},['#f43f5e','#f59e0b','#10b981','#06b6d4','#8b5cf6','#64748b'].map(color=>/*#__PURE__*/React.createElement("button",{key:color,className:"w-5 h-5 rounded-full border border-zinc-700 hover:scale-110 active:scale-95 transition",style:{backgroundColor:color},onClick:()=>{handleSetTabColor(tabContextMenu.tabId,tabContextMenu.tabType,color);setTabContextMenu(null);}})))),/*#__PURE__*/React.createElement(AuthModal,{isOpen:authModalOpen,mode:authMode,forceMandatory:isMandatoryLogin,onClose:()=>setAuthModalOpen(false),onSuccess:handleAuthSuccess}),/*#__PURE__*/React.createElement(ProfileModal,{isOpen:profileModalOpen,onClose:()=>setProfileModalOpen(false),tracks:tracks,setTracks:setTracks,setSelectedTrackId:setSelectedTrackId,projectName:projectName,setProjectName:setProjectName,currentProjectId:currentProjectId,setCurrentProjectId:setCurrentProjectId,showToast:showToast}),/*#__PURE__*/React.createElement(SaveProjectModal,{isOpen:saveProjectModalOpen,onClose:()=>setSaveProjectModalOpen(false),onSave:newName=>{handleSaveProjectWithName(newName);}}),/*#__PURE__*/React.createElement(SaveAsModal,{isOpen:saveAsModalOpen,onClose:()=>setSaveAsModalOpen(false),projectName:projectName,onSaveCloud:newName=>{handleSaveAsCloud(newName);},onSaveLocal:newName=>{handleExportSFS(newName);setProjectName(newName);localStorage.setItem('sonic_project_name',newName);}}),/*#__PURE__*/React.createElement(AIConfigModal,{isOpen:aiConfigModalOpen,onClose:()=>setAiConfigModalOpen(false),onConfigSaved:providers=>{setAiProviders(providers);const active=providers.find(p=>p.is_active)||providers[0];if(active)setSelectedProviderId(active.id);}}),/*#__PURE__*/React.createElement(SystemManagerModal,{isOpen:systemManagerModalOpen,onClose:()=>setSystemManagerModalOpen(false)}),/*#__PURE__*/React.createElement(PluginManagerModal,{isOpen:pluginManagerModalOpen,onClose:()=>setPluginManagerModalOpen(false),pluginsData:pluginsData}),/*#__PURE__*/React.createElement(AIPresetModal,{isOpen:aiPresetModalOpen,onClose:()=>setAiPresetModalOpen(false)}),instrumentSelectorTrackId&&/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm",onClick:closeInstrumentSelector},/*#__PURE__*/React.createElement("div",{className:"bg-[#262626] border border-[#383838] rounded-xl shadow-2xl w-full max-w-md p-5 text-slate-200",onClick:e=>e.stopPropagation()},synthCategory==='soundfont'?(/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{className:"flex justify-between items-center pb-3 border-b border-[#383838]"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("button",{onClick:()=>{setSynthCategory(null);setSelectedSoundFontId(null);},className:"text-[10px] text-cyan-400 hover:text-cyan-300 mr-2"},"\u2190 Back"),/*#__PURE__*/React.createElement("h3",{className:"text-sm font-bold inline text-amber-400"},"Select Instrument")),/*#__PURE__*/React.createElement("button",{onClick:closeInstrumentSelector,className:"text-slate-400 hover:text-slate-200"},"\u2715")),/*#__PURE__*/React.createElement("p",{className:"text-[10px] text-zinc-500 mt-2 mb-2"},"SoundFont: ",selectedSoundFontId),/*#__PURE__*/React.createElement("div",{className:"mt-2 max-h-72 overflow-y-auto space-y-0.5"},/*#__PURE__*/React.createElement("button",{onClick:()=>setTrackInstrumentWithProgram(instrumentSelectorTrackId,selectedSoundFontId),className:"w-full text-left px-3 py-1.5 text-xs rounded bg-zinc-800 hover:bg-zinc-700 text-zinc-400"},"None (Default Program)"),sfPresets===null?React.createElement("p",{className:"text-[10px] text-zinc-500 py-2"},"Loading instruments..."):sfPresets.length>0?React.createElement("div",{className:"grid grid-cols-2 gap-0.5"},sfPresets.map((p,i)=>React.createElement("button",{key:i,onClick:()=>setTrackInstrumentWithProgram(instrumentSelectorTrackId,selectedSoundFontId,p.program,p.name||'Preset '+p.program),className:"text-left px-2 py-1 text-[10px] rounded bg-zinc-800/60 hover:bg-amber-800 text-zinc-300 truncate"},p.name||'Preset '+p.program))):React.createElement("p",{className:"text-[10px] text-zinc-500 py-2"},"No presets found.")))):(/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{className:"flex justify-between items-center pb-3 border-b border-[#383838]"},/*#__PURE__*/React.createElement("h3",{className:"text-sm font-bold text-violet-400"},"Synth Selector")),/*#__PURE__*/React.createElement("div",{className:"mt-3 max-h-80 overflow-y-auto space-y-1"},/*#__PURE__*/React.createElement("button",{onClick:()=>setTrackInstrumentWithProgram(instrumentSelectorTrackId,null),className:"w-full text-left px-3 py-2 text-xs rounded bg-zinc-800 hover:bg-zinc-700 text-zinc-400"},"None (Default Synth)"),/*#__PURE__*/React.createElement("div",{className:"text-[10px] text-zinc-500 mt-2 mb-1 uppercase font-bold"},"SoundFonts"),instrumentSelectorData?.soundfonts?.map((sf,i)=>/*#__PURE__*/React.createElement("button",{key:"sf_"+i,onClick:()=>setTrackInstrument(instrumentSelectorTrackId,"sf_"+sf.id,sf.display||sf.name||sf.id),className:"w-full text-left px-3 py-2 text-xs rounded bg-zinc-800 hover:bg-amber-800 text-zinc-200 flex items-center justify-between"},/*#__PURE__*/React.createElement("span",null,sf.display||sf.name||sf.id),/*#__PURE__*/React.createElement("span",{className:"text-[10px] text-amber-400"},"SoundFont"))),/*#__PURE__*/React.createElement("div",{className:"text-[10px] text-zinc-500 mt-2 mb-1 uppercase font-bold"},"VST Instruments"),instrumentSelectorData?.vst_instruments?.map((v,i)=>/*#__PURE__*/React.createElement("button",{key:"vst_"+i,onClick:()=>setTrackInstrumentWithProgram(instrumentSelectorTrackId,v.id,undefined,v.name||v.id),className:"w-full text-left px-3 py-2 text-xs rounded bg-zinc-800 hover:bg-violet-900 text-zinc-200 flex items-center justify-between"},/*#__PURE__*/React.createElement("span",null,v.name||v.id),/*#__PURE__*/React.createElement("span",{className:"text-[10px] text-cyan-400"},v.type))),(!instrumentSelectorData||!instrumentSelectorData.vst_instruments?.length&&!instrumentSelectorData.soundfonts?.length)&&/*#__PURE__*/React.createElement("p",{className:"text-xs text-zinc-500 py-4 text-center"},"No plugins available. Upload SoundFont via Tools \u2192 Plugin Manager.")))))),fxSelectorTrackId&&/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm",onClick:()=>setFxSelectorTrackId(null)},/*#__PURE__*/React.createElement("div",{className:"bg-[#262626] border border-[#383838] rounded-xl shadow-2xl w-64 p-4 text-slate-200",onClick:e=>e.stopPropagation()},/*#__PURE__*/React.createElement("h3",{className:"text-sm font-bold text-purple-400 mb-3"},"Track FX"),/*#__PURE__*/React.createElement("div",{className:"space-y-1"},/*#__PURE__*/React.createElement("button",{onClick:()=>handleSetTrackFx(fxSelectorTrackId,null),className:"w-full text-left px-3 py-2 text-xs rounded bg-zinc-800 hover:bg-zinc-700 text-zinc-400"},"None"),/*#__PURE__*/React.createElement("button",{onClick:()=>handleSetTrackFx(fxSelectorTrackId,'chorus'),className:"w-full text-left px-3 py-2 text-xs rounded bg-zinc-800 hover:bg-cyan-800 text-cyan-300"},"Chorus"),/*#__PURE__*/React.createElement("button",{onClick:()=>handleSetTrackFx(fxSelectorTrackId,'reverb'),className:"w-full text-left px-3 py-2 text-xs rounded bg-zinc-800 hover:bg-purple-800 text-purple-300"},"Reverb")))),instrumentDropdownTrackId&&instrumentDropdownBtnRect&&/*#__PURE__*/React.createElement("div",{"data-instr-dropdown":"",className:"fixed z-[100] bg-[#1e1e1e] border border-zinc-700 rounded shadow-xl w-[220px] max-h-[300px] flex flex-col",style:{top:instrumentDropdownBtnRect.bottom+4,left:Math.max(4,Math.min(instrumentDropdownBtnRect.left,window.innerWidth-224))}},/*#__PURE__*/React.createElement("input",{type:"text",placeholder:"T\u00ecm nh\u1ea1c c\u1ee5...",value:instrumentSearchQuery,onChange:e=>setInstrumentSearchQuery(e.target.value),autoFocus:true,className:"w-full bg-black border-b border-zinc-700 px-2 py-1.5 text-xs outline-none"}),/*#__PURE__*/React.createElement("div",{className:"flex-1 overflow-y-auto"},/*#__PURE__*/React.createElement("button",{onClick:()=>setTrackInstrumentWithProgram(instrumentDropdownTrackId,null),className:"w-full text-left px-3 py-1.5 text-xs bg-zinc-800 hover:bg-zinc-700 text-zinc-400"},"None (Default Synth)"),filteredInstruments.soundfonts.length>0&&/*#__PURE__*/React.createElement("div",{className:"text-[10px] text-zinc-500 px-3 py-1 mt-1 uppercase font-bold"},"SoundFonts"),filteredInstruments.soundfonts.map((sf,i)=>/*#__PURE__*/React.createElement("button",{key:"sfd_"+i,onClick:()=>{setInstrumentDropdownTrackId(null);setInstrumentDropdownBtnRect(null);setTrackInstrument(instrumentDropdownTrackId,"sf_"+sf.id,sf.display||sf.name||sf.id);},className:"w-full text-left px-3 py-1.5 text-xs bg-zinc-800 hover:bg-amber-800 text-zinc-200 flex items-center justify-between"},/*#__PURE__*/React.createElement("span",{className:"truncate"},sf.display||sf.name||sf.id),/*#__PURE__*/React.createElement("span",{className:"text-[10px] text-amber-400 shrink-0 ml-1"},"SF"))),filteredInstruments.vst.length>0&&/*#__PURE__*/React.createElement("div",{className:"text-[10px] text-zinc-500 px-3 py-1 mt-1 uppercase font-bold"},"VST Instruments"),filteredInstruments.vst.map((v,i)=>/*#__PURE__*/React.createElement("button",{key:"vstd_"+i,onClick:()=>{setInstrumentDropdownTrackId(null);setInstrumentDropdownBtnRect(null);setTrackInstrumentWithProgram(instrumentDropdownTrackId,v.id,undefined,v.name||v.id);},className:"w-full text-left px-3 py-1.5 text-xs bg-zinc-800 hover:bg-violet-800 text-zinc-200 flex items-center justify-between"},/*#__PURE__*/React.createElement("span",{className:"truncate"},v.name||v.id),/*#__PURE__*/React.createElement("span",{className:"text-[10px] text-cyan-400 shrink-0 ml-1"},v.type||"VST"))),!filteredInstruments.soundfonts.length&&!filteredInstruments.vst.length&&/*#__PURE__*/React.createElement("p",{className:"text-xs text-zinc-500 py-4 text-center"},"Kh\u00f4ng t\u00ecm th\u1ea5y nh\u1ea1c c\u1ee5 n\u00e0o"))));};const root=ReactDOM.createRoot(document.getElementById('root'));root.render(/*#__PURE__*/React.createElement(App,null));setTimeout(()=>lucide.createIcons(),300);