Commit Graph

142 Commits

Author SHA1 Message Date
3dtours a1767e338a fix: Select Instrument stays open after picking instrument
Remove setInstrumentSelectorTrackId(null) from
setTrackInstrumentWithProgram. Modal stays open so user can
switch tracks and assign instruments without reopening.
2026-07-29 11:56:26 +07:00
3dtours 8051cf3edb fix: add missing aiTypeaheadRef definition 2026-07-29 11:52:49 +07:00
3dtours 35e767795a fix: Synth button opens modal with inline track selector
Remove external track dropdown. Add select dropdown inside the
instrument selector modal between title and search box. Users
can switch tracks without closing the modal.
2026-07-29 11:52:12 +07:00
3dtours 7bfdd72850 feat: Synth button shows track dropdown for quick instrument assign
Synth button opens a dropdown listing all tracks instead of opening
the modal directly. Selecting a track opens the instrument selector
for that track. No need to close modal and click each track's Synth.
2026-07-29 11:49:34 +07:00
3dtours 41b5a70a60 fix: AI SUGGEST auto-updates after saving preset in manager
Add aiPresetVersion counter. Increment on modal close. AI panel
compares version and calls loadPresets() to sync from localStorage.
2026-07-29 11:45:31 +07:00
3dtours a3e681afc0 fix: re-fetch instrument data after login for new machines
Auth success handler now eagerly loads instrumentSelectorData
via listPlugins + getSoundfontCatalog. The mount-time useEffect
runs before auth token is set, so it silently fails on new machines.
2026-07-29 11:34:50 +07:00
3dtours 8775c960e3 fix: seed_admin() no longer resets admin password on restart
Remove hash verification + password reset logic. seed_admin() now
only creates the admin account if it does not exist. Prevents
password being reset to default + must_change_password flag
being set on every server restart.
2026-07-29 11:28:49 +07:00
3dtours d4262acb9f fix: rewrite drag handler with stable crossOffset + outTracks merge 2026-07-29 11:13:31 +07:00
3dtours e40fdf15ad fix: use original baseTrackId for crossOffset, never update drag.trackId 2026-07-29 11:10:59 +07:00
3dtours 0d763c5a0b fix: targetTrackId undefined outside updateActiveTracks closure
Move track Y-position computation before updateActiveTracks so
targetTrackId is accessible for setDraggedSectionItem update.
2026-07-29 11:09:05 +07:00
3dtours ad6fa1feb9 fix: auto-add tracks when drag exceeds track count
Compute maxTargetIdx across all multiIds items. Prepend new
tracks to prev array before mapping if needed.
2026-07-29 11:08:11 +07:00
3dtours 9abb0e6a50 fix: cross-track drag computes target from mouse Y position
Replace hoveredTrackIdRef with Y-position calculation through
track heights from prev state. Works reliably during drag.
2026-07-29 11:03:30 +07:00
3dtours 6c6a326b7d fix: single-item cross-track drag
Each track filters the item independently. Only target track
receives the inserted item. Removes duplicate state update.
2026-07-29 11:02:03 +07:00
3dtours 8e8fc58082 fix: group drag uses original trackId for offset math
Store trackId in multiIds at drag start. Each item computes
target from original track + crossOffset, immune to stale state
from previous drag events. Track 1 item drags n tracks -> track
1+n, track 2 item -> track 2+n, etc.
2026-07-29 11:00:51 +07:00
3dtours ec355da58d fix: group drag cross-track uses live prev state for index mapping
Build trkIds from prev (updateActiveTracks callback) instead of
stale activeTracksRef. Fix srcItem lookup with proper for loop.
2026-07-29 10:55:39 +07:00
3dtours 9c3a435f26 fix: group drag cross-track maintains relative track offsets
Each item computes its own target track as srcIdx + crossOffset.
Items from different source tracks land on different target tracks,
preserving the group's vertical layout shape.
2026-07-29 10:52:50 +07:00
3dtours 12d2639455 fix: group drag keeps items on their original tracks
Remove all cross-track logic in multiIds path. Each item only
updates its time position (delta) on its current track. No
merging or track reassignment.
2026-07-29 10:50:37 +07:00
3dtours e99bc8624f fix: group drag moves all items, clamp to track 0, auto-add track
Restore multiIds cross-track move for all selected items.
Clamp targetTrackId to first track. Auto-add new track via
addNewTrack() when dragging below the last track.
2026-07-29 10:47:53 +07:00
3dtours 9869566d3e fix: multi-item drag no longer merges all items into target track
Only the dragged item (drag.itemId) crosses tracks. Other selected
items stay on their original tracks and only move horizontally.
2026-07-29 10:42:42 +07:00
3dtours e544d5e694 fix: show all presets always, no filter by selection
Remove selection-based filter entirely. Suggestions list stays
stable across select/deselect — no preset appears at top when
deselecting.
2026-07-29 10:18:47 +07:00
3dtours 614d83b971 fix: filter excludes non-rearrange presets in AI suggestion list
Remove || p.is_favorite from filter when MIDI item selected.
Only presets with category === 'Rearrange / Variation' appear.
2026-07-29 10:17:36 +07:00
3dtours 895ad0b7d9 fix: restore AI suggestion filter by selection, cache PromptTemplateManager
Cache PromptTemplateManager in ref to prevent new instance per
render. Filter: show only Rearrange/favorites when MIDI item
selected, all presets otherwise. Root cause of 'suggestion added
at top' was stale array reference from new instance every render.
2026-07-29 10:11:10 +07:00
3dtours 98ca21bd9a fix: AI Suggestion list changing on item select/deselect
Always show full preset list instead of filtering to rearrange/
favorites when item selected. Prevents suggestion list from
visually changing during selection/deselection.
2026-07-29 10:08:05 +07:00
3dtours 5ed943b3d6 fix: stuck MIDI notes when ARM toggled off mid-note
Remove !st.isArmed guard in note-off handler. Stop note on ALL
tracks regardless of ARM state — FluidSynth stopNote on inactive
channel/pitch is a no-op, so this is safe.
2026-07-29 10:02:30 +07:00
3dtours b00f0cff95 feat: mixer VU meter, fader scaling, track name color
- Master strip: add fader placeholder + VU meter bar
- MixerStrip: items-end -> items-stretch so fader + VU fill height
- VU meter: bar height maps volumeDb, color green/amber/red
- Track name uses track.color instead of fixed text-zinc-400
2026-07-29 09:54:18 +07:00
3dtours 2187440681 feat: Mixer Panel display-only with F7 toggle
Add MixerStrip component for display-only track strips (no audio
routing). Mixer panel at bottom with drag resize handle (80-400px).
F7 keyboard shortcut, status bar toggle button, View menu item.
onUpdateTrack handles mute/solo/volume changes directly on tracks.
2026-07-29 09:49:47 +07:00
3dtours bb49035bee fix: sửa lỗi xóa track khi nhấn phím Del, đúng là phải xóa items được chọn 2026-07-28 19:34:47 +07:00
3dtours cff3950670 feat: AI Copilot suggestion chips + typeahead dropdown
- Suggestion chips bar: context-aware (amber for rearrange, indigo for creation)
- Typeahead dropdown: keyword matching on ≥2 chars, Tab to select
- getSelectedMidiItemInfo helper for context detection
- Backend: 4 rearrange presets in ai_presets.py
- PromptTemplateManager: getContextualSuggestions(hasSelectedItem)
2026-07-28 11:20:26 +07:00
3dtours 3f7abe0c95 feat: AI Rearrange Scenario Detection from spec 45_SCENARIAO_AI
- 9 rearrange scenarios with keyword matching (arpeggio, harmonies,
  syncopation, walking bass, jazz, synthwave, cinematic, simplify, chromatic)
- detectRearrangeScenario() maps user prompt to specific technique rules
- buildRearrangeMessage auto-injects scenario-specific technique guidance
- 9 rearrange presets added to PromptTemplateManager (Rearrange / Variation)
2026-07-28 11:03:26 +07:00
3dtours 2eb327056d fix: MIDI Rearrange — selected item triggers dedicated tool flow
- midiExtractor.js: extractSelectedMIDIContext with note name conversion
- aiGateway.js: REARRANGE_TOOL_SPEC + buildRearrangeMessage
- dawCommandDispatcher.js: register REARRANGE_MIDI_MELODY command
- app.jsx: handleAISend detects selected MIDI item → rearrange flow
- rearrangeMidiMelody handler places A/B track below source track
2026-07-28 10:54:35 +07:00
3dtours 421535ca0e feat: AI MIDI Prompt Template & Preset Engine
- promptTemplateManager.js: standalone service with keyword scoring, CRUD, fav toggle
- ai_presets.py: backend CRUD router (JSON file, auth isolation)
- AIPresetModal: PromptTemplateManager, star/fav column, backend API sync
- Piano Roll AI: preset matching support
- 7 tests: matching, CRUD, anonymous auth, user isolation
2026-07-28 10:42:30 +07:00
3dtours 10c0a743c6 feat: CC lane dropdown with Velocity, Sustain, Modulation, Pitch Bend, Pan
Replaced flex div with velocity/pan buttons with a
<select> dropdown containing 5 CC type options.
Default: Velocity. Button toggle shows short label.
2026-07-28 10:20:52 +07:00
3dtours b5f3f987b7 fix: Ctrl+click empty space starts sweep select with yellow cursor
Line 1163 called onSweepSelectStart which set up sweep
state (yellow selection rectangle). Mousemove then
selected all items in the sweep range. Changed to
onClearSelection = () => setSelectedItemIds(new Set())
which only clears selection without starting sweep.
2026-07-28 10:10:05 +07:00
3dtours 5ec329933a fix: Ctrl+S in SECTION-TAB exports SF instead of saving section
First Ctrl+S handler (line 8066, handleExportSFS) catches
ALL Ctrl+S before second handler (line 8157, save section)
ever runs. Moved section-tab check into first handler:
activeTab.startsWith('session_') -> handleSaveSectionTab.
Main session Ctrl+S still exports SF (same as before).
2026-07-28 10:07:02 +07:00
3dtours 62a41d4502 fix: Ctrl+S saves section in SECTION-TAB, Ctrl+A selects all items
Ctrl+S in SECTION-TAB (activeTab starts with session_):
calls handleSaveSectionTab(curTab).
Ctrl+A in MAIN/SECTION-TAB: collects sections, midiItems,
clips from activeTracksRef.current into selectedItemIds.
Ignores sub-tab contexts (PIANO_ROLL).
2026-07-28 09:59:13 +07:00
3dtours 385d62cfaf fix: Insert Section visible in SECTION-TAB context menu
JSX rendering menu at line 17500 lacked the
!sessionTabs.some(s => s.id === activeTab) guard.
Added it - section tab context menu no longer offers
Insert Section (sections cannot contain section items).
2026-07-28 09:55:37 +07:00
3dtours 32b61553f9 fix: program_change at call time overrides subsequent notes
_playNoteFluid called program_change synchronously at
call time, not at scheduled note time. startTrackPlayback
processes all MIDI items first, then all sections -> each
note's program_change overwritten by the last type processed.
All notes played with section instrument regardless of
actual time position. Moved program_change into doNote
(setTimeout callback) so it fires at correct time.
2026-07-28 09:48:54 +07:00
3dtours 43691a127e fix: section track plays GM Piano via program default 0
section cloned tracks have instrumentProgram:undefined.
Line 10283 defaulted to 0 -> FluidSynth program_change(ch,0)
-> plays whatever SoundFont is loaded (MAIN SF).
Added _isSectionClone flag; line 10283 skips program default
for section clones -> undefined -> _playNoteFluid silent return.
2026-07-28 09:30:27 +07:00
3dtours 6fa6578dd1 feat: silent fallback when no instrument — no oscillator default
_playNoteFluid no-instrument branch previously called
_playNoteFallback (sine wave oscillator). Changed to
silent return. User explicitly requested no default sound.
2026-07-28 09:28:21 +07:00
3dtours 2dec94aa7e fix: restore program default 0 for MAIN track MIDI playback
Line 10283 defaulted to undefined when instrumentProgram
undefined, breaking Play for MAIN tracks with MIDI items
but no instrument. Restored: undefined ? instrumentProgram : 0.
Section sub-track (line 10393) keeps undefined -> oscillator
fallback to avoid loading MAIN SoundFont.
2026-07-28 09:25:50 +07:00
3dtours ea40f0c540 revert: playhead fixes cause cannot play on MAIN/SECTION-TAB
Revert two changes from 5d31563:
1. Explicit requestAnimationFrame in handlePlayPause (redundant,
   useEffect already handles RAF start after setIsPlaying)
2. setCurrentTime(0) in handleEditSectionInTab (resets global
   currentTime, interferes with MAIN session position)
2026-07-28 09:22:44 +07:00
3dtours 5d31563df6 fix: playhead not moving in SECTION-TAB with empty tracks
Two fixes:
1. handlePlayPause: add explicit requestAnimationFrame(updatePlayhead)
   after setIsPlaying(true) to ensure RAF starts immediately.
2. handleEditSectionInTab: add setCurrentTime(0) to reset playhead
   to section start. Without this, currentTime may be outside
   the section's timeline range (e.g. from main session playback).
2026-07-28 09:20:31 +07:00
3dtours 2f2f84066c fix: main playback default program 0 loads MAIN SoundFont
Line 10283 same issue as 10393: when instrumentProgram is
undefined (section cloned tracks), program defaults to 0.
_playNoteFluid calls program_change(ch,0) on FluidSynth,
which loads program 0 from whatever SoundFont is loaded
(MAIN session's SF). Fix: pass undefined -> oscillator
fallback for all tracks without assigned instrument.
2026-07-28 09:15:51 +07:00
3dtours 52ec9379d6 fix: section sub-track MIDI default program 0 loads MAIN SoundFont
Line 10393 defaulted program to 0 when subTrack.instrumentProgram
was undefined (section clone with no instrument). _playNoteFluid
receives program=0, calls program_change(ch,0) on FluidSynth,
which picks program 0 from whatever SoundFont is loaded (MAIN
session's SF). Fix: pass undefined -> _playNoteFluid takes
oscillator fallback, no SoundFont loading.
2026-07-28 09:10:33 +07:00
3dtours 9c2fa52e1b revert: Synth button conditional on section items - track can have both
815a6fa hid Synth when track has sections. But a track
can contain both section items AND midi items. Synth
applies to MIDI items regardless of sections. Section
instrument isolation is handled by section clone
nullifying all soundfont fields (9befc20).
2026-07-28 08:50:13 +07:00
3dtours 815a6faaca fix: Synth button shown on section/audio tracks
Synth button was unconditional in TCP. Now gated:
track.midiItems?.length > 0 && !track.sections?.length
Section tracks: Synth hidden (sections are containers).
MIDI tracks: Synth shown.
Audio tracks: Synth hidden.
FX button stays unconditional for all track types.
2026-07-28 08:37:31 +07:00
3dtours 9befc20851 fix: section track inherits soundfont_id/bank/program via ...t spread
...t in fallback branch copied soundfont_id, soundfont_bank,
soundfont_program, instrument_source from parent MAIN track
even though instrumentProgram and synth_engine were nulled.
FluidSynth picks up these fields and auto-loads the SoundFont.
Fix: override all soundfont/synth fields to null/undefined.
2026-07-28 08:32:21 +07:00
3dtours 18e177fa2d revert: section tracks inherit parent instrument, auto-loads SF prog0
Previous fix f2ac70e inherited instrumentId/program/name
from parent MAIN track. This causes SECTION-TAB to auto-load
program 0 of whatever SoundFont is loaded on MAIN, even
though user didn't select any instrument for the section.
Section tracks now keep null instrument + synth_engine
undefined. User can still load instrument manually via
Synth button (routed by updateActiveTracks fix).
2026-07-28 08:27:27 +07:00
3dtours f2ac70eee0 fix: section sub-tracks nullify instrument instead of inheriting
handleEditSectionInTab fallback branch explicitly set
instrumentId: null, instrumentProgram: undefined,
instrumentName: null, overriding parent track's values
spread by ...t. Changed to inherit from parent track:
instrumentId: t.instrumentId || null,
instrumentProgram: t.instrumentProgram,
instrumentName: t.instrumentName || null
2026-07-28 08:18:43 +07:00
3dtours ed51cab765 fix: instrument load from PIANO_ROLL in SECTION-TAB writes to main
updateActiveTracksRef checks sessionTabs by currentActiveTab.
When activeTab is a PIANO_ROLL sub-tab (midi_xxx), none matches
-> falls to setTracks (main). Instrument changes are lost.
Fix: also check subTabs for PIANO_ROLL type, resolve parent
session tab via parent_tab_id, route to setSessionTabs.
2026-07-28 08:11:36 +07:00