- Transport: play/stop/back/next/record buttons in piano roll toolbar
- ARM toggle + MIDI input device selector next to Snap to Scale
- AI bar range selector (bar X to bar Y) for Copilot MIDI generation
- handleAISend detects active piano roll tab and routes MIDI prompt
- Added selectedMidiInputId state + handleMidiInputSelect for MIDI input
Piano roll AI prompt now selects provider via same logic as main AI
handler (aiProviders, selectedProviderId, baseUrl, apiKey, model).
No longer hardcodes provider:'openai', model:'gpt-4o'.
- Removed aiPrompt/aiLoading state and handleAIPrompt from PianoRollTabEditor
- Removed AI prompt input UI from piano roll toolbar
- handleAISend now detects active piano roll tab and routes
prompts to MIDI note generation, appends notes to the tab
- Initial click note pitch now snaps when snapToScale is on
- Added snapToScaleRef and selectedScaleRef for stale-closure safety
- All brush-draw snap paths (mousedown + mousemove) use refs
- Added snapToScale state + toggle switch in piano roll toolbar
- snapPitchToScale only applies when snapToScale is true
- Removed Select/Pen/Eraser tool buttons
- Right-click drag erase sweep sets swallowContextMenuRef=true
so context menu won't appear during sweep
- Separate swallowContextMenuRef (not tied to rightClickDragRef) so
menu is skipped on right-click delete
- Initial click draw uses raw pitch, not snapPitchToScale (scale only
applies during brush-drag in mousemove)
Right-click on note = delete.
Right-click empty space (no drag) = context menu only (no erase sweep).
Right-click empty space + drag >5px = erase sweep (starts on mousemove).
Uses rightClickDragRef to track pending right-click state.
ActiveRollTool default changed from 'select' to 'pen' so clicking
empty space draws notes immediately. Users who switch tool must
switch back to 'pen' to draw.
Sub-menu items now render as a standalone fixed-position panel
at origin.x+150, not mixed into the main menu. Main menu stays
at its initial position. Hover to open, click to select scale.
- Context menu (Scales) appears at right-click position on grid canvas
- Removed erase sweep on right-click (blocked brush after menu close)
- Removed keybed onContextMenu (was wrong position)
- Store menu origin ref so sub-menus don't drift on hover
- Brush (pen tool only) draws notes snapped to selected scale
- Scale sub-menus open on hover instead of click
- Keybed: swipe/drag across keys plays notes (mouseenter+mousedown)
- Global mouseup resets keybed drag state
When section duration is resized shorter, sub-track clips and MIDI
notes were still drawn outside the section's visual rectangle.
Added ctx.save/clip/restore around sub-track rendering.
6 render positions (clip, marker, section, MIDI, note, selection) were
using React prop scrollLeft instead of DOM scrollLeftVal, causing
grid-vs-item desync during fast auto-scroll.
- PADDING_LEFT=0 in all 3 components (grid aligns with clip origin)
- TempoTrackLane/WaveformLane tEnd uses CLIP_BUFFER/zoom so bars render past right edge
- TimelineRuler tEnd uses CLIP_BUFFER/zoom instead of PADDING_LEFT
- Removed Math.max(beatSec, ...) clamp from clip drag, section drag, section resize handlers
- Replaced with Math.max(0, ...) so items can snap to time 0