Files
SonicForgeStudio/app/static/js/services/dawCommandDispatcher.js
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

93 lines
3.1 KiB
JavaScript

// SonicForge Studio - DAW Command Dispatcher
// Command Pattern & Undo/Redo Engine (28_AI_PANEL.md §1 & §2)
const DAWCommandDispatcher = (function() {
const MAX_HISTORY = 50;
const history = [];
let historyIndex = -1;
function pushHistory(entry) {
history.push(entry);
if (history.length > MAX_HISTORY) history.shift();
historyIndex = history.length - 1;
}
function undo() {
if (historyIndex < 0) return null;
const entry = history[historyIndex];
historyIndex--;
return entry;
}
function redo() {
if (historyIndex >= history.length - 1) return null;
historyIndex++;
const entry = history[historyIndex];
return entry;
}
function canUndo() { return historyIndex >= 0; }
function canRedo() { return historyIndex < history.length - 1; }
const registry = {};
function register(name, handler) {
registry[name] = handler;
}
function execute(name, args) {
if (!registry[name]) {
return { success: false, error: `Unknown command: ${name}` };
}
const result = registry[name](args);
pushHistory({ name, args, result, timestamp: Date.now() });
return result;
}
function getHistory() { return history; }
function getHistoryIndex() { return historyIndex; }
function registerDAWCommands(api) {
register('CREATE_TRACK', (args) => api.createTrack(args));
register('DELETE_TRACK', (args) => api.deleteTrack(args));
register('ADD_CLIP', (args) => api.addClip(args));
register('REMOVE_CLIP', (args) => api.removeClip(args));
register('SET_TRACK_VOLUME', (args) => api.setTrackVolume(args));
register('SET_TRACK_PAN', (args) => api.setTrackPan(args));
register('TOGGLE_MUTE', (args) => api.toggleMute(args));
register('TOGGLE_SOLO', (args) => api.toggleSolo(args));
register('PROCESS_AUDIO_DSP', (args) => api.processAudioDsp(args));
register('RENAME_TRACK', (args) => api.renameTrack(args));
register('SCAN_TRACK', (args) => api.scanTrack(args));
register('FADE_IN', (args) => api.fadeIn(args));
register('FADE_OUT', (args) => api.fadeOut(args));
register('CUT_AUDIO', (args) => api.cutAudio(args));
register('SET_SELECTION', (args) => api.setSelection(args));
register('EXPORT_AUDIO', (args) => api.exportAudio(args));
register('SET_BPM', (args) => api.setBpm(args));
register('SET_PLAYHEAD', (args) => api.setPlayhead(args));
register('SELECT_ITEM', (args) => api.selectItem(args));
register('ADD_MARKER', (args) => api.addMarker(args));
register('CREATE_MIDI_ITEM', (args) => api.createMidiItem(args));
register('MODIFY_MIDI_NOTES', (args) => api.modifyMidiNotes(args));
register('PROCESS_AI_DSP', (args) => api.processAudioDsp(args));
register('GENERATE_MULTITRACK_MIDI', (args) => api.generateMultitrackMidi(args));
register('REARRANGE_MIDI_MELODY', (args) => api.rearrangeMidiMelody(args));
}
return {
register,
execute,
undo,
redo,
canUndo,
canRedo,
pushHistory,
getHistory,
getHistoryIndex,
registerDAWCommands
};
})();
window.DAWCommandDispatcher = DAWCommandDispatcher;