fix(ui): wire Synth button to VST3 selection and render engine
- UI: setTrackInstrumentWithProgram stores instrumentId + enables MIDI type - UI: SoundFont preset selection now passes soundfont_bank to server - Server: render_engine reads instrument_id field (fallback instrument) - Serialize/deserialize: soundfont_bank, soundfont_program preserved - Rebuilt app.precompiled.js from app.jsx
This commit is contained in:
@@ -130,7 +130,7 @@ class PythonRenderEngine:
|
|||||||
|
|
||||||
if midi_events:
|
if midi_events:
|
||||||
try:
|
try:
|
||||||
instrument_id = track.get("instrument", "")
|
instrument_id = track.get("instrument_id", "") or track.get("instrument", "")
|
||||||
plugin_mgr = PluginManager()
|
plugin_mgr = PluginManager()
|
||||||
vst = plugin_mgr.load_vst(instrument_id) if instrument_id else None
|
vst = plugin_mgr.load_vst(instrument_id) if instrument_id else None
|
||||||
|
|
||||||
|
|||||||
+10
-4
@@ -6130,6 +6130,8 @@ const serializeTracksList = (tracksList, secondsPerBar) => {
|
|||||||
instrument_id: t.instrumentId || null,
|
instrument_id: t.instrumentId || null,
|
||||||
instrument_program: t.instrumentProgram !== undefined ? t.instrumentProgram : null,
|
instrument_program: t.instrumentProgram !== undefined ? t.instrumentProgram : null,
|
||||||
instrument_name: t.instrumentName || null,
|
instrument_name: t.instrumentName || null,
|
||||||
|
soundfont_bank: t.soundfont_bank !== undefined ? t.soundfont_bank : null,
|
||||||
|
soundfont_program: t.soundfont_program !== undefined ? t.soundfont_program : null,
|
||||||
items: items
|
items: items
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -6196,7 +6198,9 @@ const deserializeTracksList = (schemaTracks, secondsPerBar, sectionStore) => {
|
|||||||
midiItems: midiItems,
|
midiItems: midiItems,
|
||||||
instrumentId: t.instrument_id || null,
|
instrumentId: t.instrument_id || null,
|
||||||
instrumentProgram: t.instrument_program !== null ? t.instrument_program : undefined,
|
instrumentProgram: t.instrument_program !== null ? t.instrument_program : undefined,
|
||||||
instrumentName: t.instrument_name || null
|
instrumentName: t.instrument_name || null,
|
||||||
|
soundfont_bank: t.soundfont_bank !== null ? t.soundfont_bank : undefined,
|
||||||
|
soundfont_program: t.soundfont_program !== null ? t.soundfont_program : undefined
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -6483,10 +6487,12 @@ const App = () => {
|
|||||||
"Tinkle Bell","Agogo","Steel Drums","Woodblock","Taiko Drum","Melodic Tom","Synth Drum","Reverse Cymbal",
|
"Tinkle Bell","Agogo","Steel Drums","Woodblock","Taiko Drum","Melodic Tom","Synth Drum","Reverse Cymbal",
|
||||||
"Guitar Fret Noise","Breath Noise","Seashore","Bird Tweet","Telephone Ring","Helicopter","Applause","Gunshot"
|
"Guitar Fret Noise","Breath Noise","Seashore","Bird Tweet","Telephone Ring","Helicopter","Applause","Gunshot"
|
||||||
];
|
];
|
||||||
const setTrackInstrumentWithProgram = (trackId, instrumentId, programNumber, displayName) => {
|
const setTrackInstrumentWithProgram = (trackId, instrumentId, programNumber, displayName, bankNumber) => {
|
||||||
updateActiveTracks(prev => prev.map(t => {
|
updateActiveTracks(prev => prev.map(t => {
|
||||||
if (t.id !== trackId) return t;
|
if (t.id !== trackId) return t;
|
||||||
return { ...t, instrumentId, instrumentProgram: programNumber !== undefined ? programNumber : undefined, instrumentName: displayName };
|
const hasInstrument = !!instrumentId;
|
||||||
|
const isSfInstrument = instrumentId && typeof instrumentId === 'string' && instrumentId.startsWith('sf_');
|
||||||
|
return { ...t, instrumentId, instrumentProgram: programNumber !== undefined ? programNumber : undefined, instrumentName: displayName, soundfont_bank: bankNumber !== undefined ? bankNumber : (isSfInstrument ? 0 : undefined), soundfont_program: programNumber !== undefined ? programNumber : undefined, type: hasInstrument ? 'MIDI' : (t.type === 'MIDI' ? 'audio' : t.type) };
|
||||||
}));
|
}));
|
||||||
setInstrumentDropdownTrackId(null);
|
setInstrumentDropdownTrackId(null);
|
||||||
setInstrumentDropdownBtnRect(null);
|
setInstrumentDropdownBtnRect(null);
|
||||||
@@ -16839,7 +16845,7 @@ const App = () => {
|
|||||||
React.createElement("div", { className: "grid grid-cols-2 gap-0.5" },
|
React.createElement("div", { className: "grid grid-cols-2 gap-0.5" },
|
||||||
sfPresets.map((p, i) => React.createElement("button", {
|
sfPresets.map((p, i) => React.createElement("button", {
|
||||||
key: i,
|
key: i,
|
||||||
onClick: () => setTrackInstrumentWithProgram(instrumentSelectorTrackId, selectedSoundFontId, p.program, p.name || 'Preset ' + p.program),
|
onClick: () => setTrackInstrumentWithProgram(instrumentSelectorTrackId, selectedSoundFontId, p.program, p.name || 'Preset ' + p.program, p.bank),
|
||||||
className: "text-left px-2 py-1 text-[10px] rounded bg-zinc-800/60 hover:bg-amber-800 text-zinc-300 truncate"
|
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)
|
}, p.name || 'Preset ' + p.program)
|
||||||
))
|
))
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -282,3 +282,9 @@
|
|||||||
- **Files:** `docker-compose.yml`
|
- **Files:** `docker-compose.yml`
|
||||||
- **Tests:** N/A
|
- **Tests:** N/A
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### [2026-07-26 16:21] Task: Implement Synth button with VST3 selection
|
||||||
|
- **Summary:** Fixed Synth button to properly select and use system-installed VST3 plugins. Fixed field name mismatch (`instrument_id` vs `instrument`) between UI and render engine. Track auto-switches to MIDI type when VST assigned. SoundFont preset selection now passes `soundfont_bank` + `soundfont_program` to server. Serialize/deserialize includes all instrument fields.
|
||||||
|
- **Files:** `app/static/js/app.jsx`, `app/static/js/app.precompiled.js`, `app/core/render_engine.py`
|
||||||
|
- **Tests:** `pytest` - 61 passed, 1 pre-existing failure.
|
||||||
|
---
|
||||||
|
|||||||
Reference in New Issue
Block a user