feat: drag-drop MIDI file creates new tracks
This commit is contained in:
+52
-1
@@ -15668,6 +15668,39 @@ const App = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ── Drop MIDI file → create new track(s) ──
|
||||||
|
const handleDropMidiToNewTracks = async (file) => {
|
||||||
|
if (!file) return;
|
||||||
|
showToast('Đang nạp MIDI: ' + file.name + '...', 'info');
|
||||||
|
try {
|
||||||
|
var arrayBuffer = await file.arrayBuffer();
|
||||||
|
var midiResult = parseMidiFile(arrayBuffer);
|
||||||
|
if (!midiResult || midiResult.length === 0) {
|
||||||
|
showToast('Không tìm thấy nốt nhạc trong file MIDI.', 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var colors = ['#0f766e', '#1d4ed8', '#701a75', '#a21caf', '#b45309', '#ca8a04', '#dc2626', '#0891b2'];
|
||||||
|
var now = Date.now();
|
||||||
|
var newTracks = midiResult.map(function(midiItem, idx) {
|
||||||
|
return {
|
||||||
|
id: 'midi_track_' + now + '_' + idx,
|
||||||
|
name: midiItem.name || (midiResult.length > 1 ? 'MIDI Track ' + (idx + 1) : (file.name || 'MIDI').replace(/\.midi?$/i, '')),
|
||||||
|
buffer: null, startTime: 0, volumeDb: 0, pan: 0,
|
||||||
|
muted: false, solo: false, color: colors[idx % colors.length],
|
||||||
|
markers: [], serverFileId: null, clips: [], sections: [],
|
||||||
|
midiItems: [midiItem],
|
||||||
|
isArmed: false, monitoringEnabled: true,
|
||||||
|
inputSource: { deviceType: 'NONE', deviceId: '' }
|
||||||
|
};
|
||||||
|
});
|
||||||
|
updateActiveTracks(function(prev) { return prev.concat(newTracks); });
|
||||||
|
if (newTracks.length > 0) setSelectedTrackId(newTracks[0].id);
|
||||||
|
showToast('Đã tải MIDI: ' + newTracks.length + ' track(s) từ ' + file.name, 'success');
|
||||||
|
} catch (err) {
|
||||||
|
showToast('Lỗi giải mã MIDI.', 'error');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// ── Synth Generators ──
|
// ── Synth Generators ──
|
||||||
const generateSynthToTrack = (trackId, type) => {
|
const generateSynthToTrack = (trackId, type) => {
|
||||||
const sampleRate = 44100;
|
const sampleRate = 44100;
|
||||||
@@ -20327,6 +20360,17 @@ const App = () => {
|
|||||||
}
|
}
|
||||||
})), /*#__PURE__*/React.createElement("div", {
|
})), /*#__PURE__*/React.createElement("div", {
|
||||||
className: "flex-1 flex flex-col divide-y divide-[#141414] relative bg-[#111111] min-h-full",
|
className: "flex-1 flex flex-col divide-y divide-[#141414] relative bg-[#111111] min-h-full",
|
||||||
|
onDragOver: e => e.preventDefault(),
|
||||||
|
onDrop: e => {
|
||||||
|
e.preventDefault();
|
||||||
|
const f = e.dataTransfer.files && e.dataTransfer.files[0];
|
||||||
|
if (!f) return;
|
||||||
|
if (/\.mid$|\.midi$/i.test(f.name || '')) {
|
||||||
|
handleDropMidiToNewTracks(f);
|
||||||
|
} else if (selectedTrackId) {
|
||||||
|
loadFileOnTrack(selectedTrackId, f);
|
||||||
|
}
|
||||||
|
},
|
||||||
onMouseDown: e => {
|
onMouseDown: e => {
|
||||||
if (e.ctrlKey && !e.shiftKey && !e.altKey && e.button === 0) {
|
if (e.ctrlKey && !e.shiftKey && !e.altKey && e.button === 0) {
|
||||||
const wrapper = timelineWrapperRef.current;
|
const wrapper = timelineWrapperRef.current;
|
||||||
@@ -20351,7 +20395,14 @@ const App = () => {
|
|||||||
onDragOver: e => e.preventDefault(),
|
onDragOver: e => e.preventDefault(),
|
||||||
onDrop: e => {
|
onDrop: e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (e.dataTransfer.files[0]) loadFileOnTrack(track.id, e.dataTransfer.files[0]);
|
e.stopPropagation();
|
||||||
|
const f = e.dataTransfer.files && e.dataTransfer.files[0];
|
||||||
|
if (!f) return;
|
||||||
|
if (/\.mid$|\.midi$/i.test(f.name || '')) {
|
||||||
|
handleDropMidiToNewTracks(f);
|
||||||
|
} else {
|
||||||
|
loadFileOnTrack(track.id, f);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onMouseEnter: () => { setHoveredTrackId(track.id); hoveredTrackIdRef.current = track.id; }
|
onMouseEnter: () => { setHoveredTrackId(track.id); hoveredTrackIdRef.current = track.id; }
|
||||||
}, /*#__PURE__*/React.createElement(WaveformLane, {
|
}, /*#__PURE__*/React.createElement(WaveformLane, {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user