Fix AI proxy origin in Tauri, SF2 program_select, VSTi GUI reopen + sample rate bridge
- aiGateway.js: use window.API_BASE_URL (engine port) instead of window.location.origin (tauri://localhost asset protocol returned index.html -> JSON parse error); check content-type before parsing response - NativeInstrumentEngine.cpp: fluid_synth_program_select for SF2 instrument + program change - Vst3Instrument.cpp: activate all audio/event buses, channel=0 forced, GUI resize/reopen, kEvent using fix - main.cpp: VST GUI reopen via WM_DESTROY, OleInitialize, steady_clock loop - lib.rs: BridgeSampleRate state, restart_bridge_with_sample_rate command, borrow fix - app.jsx/nativeBridgeService.js: isMidiTrack widening, bridge masterbus connect, held MIDI notes, sample-rate restart, openNativeGUI channel
This commit is contained in:
+34
-5
@@ -1416,6 +1416,20 @@ function getAudioContext() {
|
||||
window.SonicMidiRouter.setBridgeConnected(connected);
|
||||
console.log('[Bridge] bootstrap connected=', connected);
|
||||
if (connected) {
|
||||
try {
|
||||
console.log('[Bridge] Requesting restart to match sampleRate:', audioCtx.sampleRate);
|
||||
await window.__TAURI__.core.invoke('restart_bridge_with_sample_rate', { sampleRate: audioCtx.sampleRate });
|
||||
for (var retry = 0; retry < 10; retry++) {
|
||||
await new Promise(r => setTimeout(r, 100));
|
||||
var st2 = await window.NativeBridgeService.queryStatus();
|
||||
if (st2 && st2.connected) {
|
||||
console.log('[Bridge] Reconnected at sampleRate:', audioCtx.sampleRate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('[Bridge] restart error:', err);
|
||||
}
|
||||
window.BridgeAudioNode.init(audioCtx);
|
||||
window.NativeBridgeService.onAudio(function (l, r) { window.BridgeAudioNode.onAudio(l, r); });
|
||||
if (window.AudioRoutingEngine) window.AudioRoutingEngine.connect(window.BridgeAudioNode, null, null);
|
||||
@@ -15378,7 +15392,7 @@ const App = () => {
|
||||
// Requirement 2: chọn VST3 qua nút Synth → load xong mở native GUI
|
||||
// (C++ attach editor vào cửa sổ bridge tự tạo — control type=4, hwnd=0).
|
||||
if (ok && btype === 'VST3' && window.NativeBridgeService.openNativeGUI) {
|
||||
try { await window.NativeBridgeService.openNativeGUI(instrumentId); } catch (e) {}
|
||||
try { await window.NativeBridgeService.openNativeGUI(instrumentId, bch); } catch (e) {}
|
||||
}
|
||||
}
|
||||
})();
|
||||
@@ -15647,6 +15661,12 @@ const App = () => {
|
||||
var bTracks = activeTracksRef.current || [];
|
||||
bTracks.forEach(function (bt) {
|
||||
if (!bt.isArmed) return;
|
||||
if (window.triggerMidiVuActivity) {
|
||||
window.triggerMidiVuActivity(bt.id, scaledVel);
|
||||
}
|
||||
try {
|
||||
heldMidiNotesRef.current[bt.id] = (heldMidiNotesRef.current[bt.id] || 0) + 1;
|
||||
} catch (err) {}
|
||||
try { window.SonicMidiRouter.pushEvent({ cmd: 'NOTE_ON', channel: bt.id, pitch: pitch, velocity: scaledVel / 127, percussion: !!(bt.synth_engine && bt.synth_engine.soundfont_bank === 128) }); } catch (e) {}
|
||||
});
|
||||
} else if (window.SonicSF) {
|
||||
@@ -15722,6 +15742,14 @@ const App = () => {
|
||||
// D1: bridge note-off qua router (channel trùng NOTE_ON — track.id).
|
||||
var bStopTracks = activeTracksRef.current || [];
|
||||
bStopTracks.forEach(function (bst) {
|
||||
try {
|
||||
if (heldMidiNotesRef.current[bst.id] !== undefined) {
|
||||
heldMidiNotesRef.current[bst.id] = Math.max(0, heldMidiNotesRef.current[bst.id] - 1);
|
||||
if (heldMidiNotesRef.current[bst.id] === 0) {
|
||||
delete heldMidiNotesRef.current[bst.id];
|
||||
}
|
||||
}
|
||||
} catch (err) {}
|
||||
try { window.SonicMidiRouter.pushEvent({ cmd: 'NOTE_OFF', channel: bst.id, pitch: pitch, velocity: 0, percussion: !!(bst.synth_engine && bst.synth_engine.soundfont_bank === 128) }); } catch (e) {}
|
||||
});
|
||||
} else if (window.SonicSF && window.SonicSF.stopNote) {
|
||||
@@ -21216,7 +21244,8 @@ const App = () => {
|
||||
// NEVER affects the soundfont instrument, and the ♪ bypass never touches
|
||||
// audio clips/sections.
|
||||
let sfEntry = null, sfOut = null, sfPan = null, sfAnalyser = null, sfRouteGain = null, sfDryGain = null, sfMods = [];
|
||||
if ((track.midiItems && track.midiItems.length > 0)) {
|
||||
const isMidiTrack = (track.midiItems && track.midiItems.length > 0) || track.type === 'MIDI' || !!track.instrumentId;
|
||||
if (isMidiTrack) {
|
||||
sfEntry = context.createGain();
|
||||
sfOut = context.createGain();
|
||||
sfPan = context.createStereoPanner();
|
||||
@@ -21401,7 +21430,7 @@ const App = () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
const midiAudible = list.filter(t => (t.midiItems && t.midiItems.length > 0) && computeTrackAudibleGain(list, t) > 0);
|
||||
const midiAudible = list.filter(t => ((t.midiItems && t.midiItems.length > 0) || t.isArmed || t.type === 'MIDI' || !!t.instrumentId) && computeTrackAudibleGain(list, t) > 0);
|
||||
console.log('[SFRoute] activeTab=' + _activeTabId, 'midiAudible=' + midiAudible.map(t => t.id + '(midi' + (t.midiItems || []).length + ')').join(',') || 'none');
|
||||
if (midiAudible.length === 1) {
|
||||
const t = midiAudible[0];
|
||||
@@ -21454,8 +21483,8 @@ const App = () => {
|
||||
}
|
||||
// D5: bridge active + không track nào audible → ngắt khỏi graph (về
|
||||
// masterBus qua updateSfRouting lần sau khi có track).
|
||||
if (window.AudioRoutingEngine && window.SonicMidiRouter && window.SonicMidiRouter.isBridgeActive()) {
|
||||
window.AudioRoutingEngine.disconnect();
|
||||
if (window.AudioRoutingEngine && window.SonicMidiRouter && window.SonicMidiRouter.isBridgeActive() && window.BridgeAudioNode) {
|
||||
window.AudioRoutingEngine.connect(window.BridgeAudioNode, null, null);
|
||||
} else if (window.SonicSF && window.SonicSF.setOutputDestination) {
|
||||
window.SonicSF.setOutputDestination(null);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user