fix: MIDI keyboard preview silent after transport STOP — live flag bypass guard (V8)
This commit is contained in:
@@ -9457,7 +9457,7 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
}
|
||||
if (window.SonicMidiRouter && window.SonicMidiRouter.isBridgeActive()) {
|
||||
try { if (window.__ensureBridgeProgram) window.__ensureBridgeProgram(kbTrk ? kbTrk.id : 0, kbCtx.program, kbCtx.synthEngine); } catch (er) {}
|
||||
window.SonicMidiRouter.pushEvent({ cmd: 'NOTE_ON', channel: kbTrk ? kbTrk.id : 0, pitch: pitch, velocity: 100 / 127, percussion: !!(kbCtx && kbCtx.synthEngine && kbCtx.synthEngine.soundfont_bank === 128) });
|
||||
window.SonicMidiRouter.pushEvent({ cmd: 'NOTE_ON', channel: kbTrk ? kbTrk.id : 0, pitch: pitch, velocity: 100 / 127, percussion: !!(kbCtx && kbCtx.synthEngine && kbCtx.synthEngine.soundfont_bank === 128), live: true });
|
||||
} else if (window.SonicSF && !kbNative) {
|
||||
// ⚠️ FIX: giữ note theo thời gian bấm phím — durationMs lớn (5s)
|
||||
// chỉ là auto-off phòng hờ; mouseup/mouseleave gọi stopNote dừng
|
||||
@@ -9485,7 +9485,7 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
}
|
||||
if (window.SonicMidiRouter && window.SonicMidiRouter.isBridgeActive()) {
|
||||
try { if (window.__ensureBridgeProgram) window.__ensureBridgeProgram(kbTrk ? kbTrk.id : 0, kbCtx.program, kbCtx.synthEngine); } catch (er) {}
|
||||
window.SonicMidiRouter.pushEvent({ cmd: 'NOTE_ON', channel: kbTrk ? kbTrk.id : 0, pitch: pitch, velocity: 100 / 127, percussion: !!(kbCtx && kbCtx.synthEngine && kbCtx.synthEngine.soundfont_bank === 128) });
|
||||
window.SonicMidiRouter.pushEvent({ cmd: 'NOTE_ON', channel: kbTrk ? kbTrk.id : 0, pitch: pitch, velocity: 100 / 127, percussion: !!(kbCtx && kbCtx.synthEngine && kbCtx.synthEngine.soundfont_bank === 128), live: true });
|
||||
} else if (window.SonicSF && !(isStandaloneSf() && isSfTrackEngine(kbCtx.synthEngine) && !shouldRouteCarla(kbCtx.synthEngine))) {
|
||||
// giữ note khi kéo qua phím (mouse enter) — dừng bằng mouseup/leave
|
||||
window.SonicSF.playNote(pitch, 100, 5000, undefined, kbCtx.program, null, kbCtx.ch, kbCtx.synthEngine);
|
||||
@@ -9504,7 +9504,7 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
try {
|
||||
if (isStandaloneSf()) stopNativeSfNote('kb_' + st.trackId + '_' + pitch);
|
||||
if (window.SonicMidiRouter && window.SonicMidiRouter.isBridgeActive()) {
|
||||
window.SonicMidiRouter.pushEvent({ cmd: 'NOTE_OFF', channel: kbTrk ? kbTrk.id : 0, pitch: pitch, velocity: 0, percussion: !!(kbCtx && kbCtx.synthEngine && kbCtx.synthEngine.soundfont_bank === 128) });
|
||||
window.SonicMidiRouter.pushEvent({ cmd: 'NOTE_OFF', channel: kbTrk ? kbTrk.id : 0, pitch: pitch, velocity: 0, percussion: !!(kbCtx && kbCtx.synthEngine && kbCtx.synthEngine.soundfont_bank === 128), live: true });
|
||||
} else if (window.SonicSF && window.SonicSF.stopNote) window.SonicSF.stopNote(kbCtx.ch, pitch);
|
||||
} catch (e) {}
|
||||
if (window.__carlaKeybedTimer) { clearTimeout(window.__carlaKeybedTimer); window.__carlaKeybedTimer = null; }
|
||||
@@ -9516,7 +9516,7 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
try {
|
||||
if (isStandaloneSf()) stopNativeSfNote('kb_' + st.trackId + '_' + pitch);
|
||||
if (window.SonicMidiRouter && window.SonicMidiRouter.isBridgeActive()) {
|
||||
window.SonicMidiRouter.pushEvent({ cmd: 'NOTE_OFF', channel: kbTrk ? kbTrk.id : 0, pitch: pitch, velocity: 0, percussion: !!(kbCtx && kbCtx.synthEngine && kbCtx.synthEngine.soundfont_bank === 128) });
|
||||
window.SonicMidiRouter.pushEvent({ cmd: 'NOTE_OFF', channel: kbTrk ? kbTrk.id : 0, pitch: pitch, velocity: 0, percussion: !!(kbCtx && kbCtx.synthEngine && kbCtx.synthEngine.soundfont_bank === 128), live: true });
|
||||
} else if (window.SonicSF && window.SonicSF.stopNote) window.SonicSF.stopNote(kbCtx.ch, pitch);
|
||||
} catch (e) {}
|
||||
if (window.SonicCarlaMidi) { try { window.SonicCarlaMidi.noteOff(kbCtx.ch, pitch); } catch (e) {} }
|
||||
@@ -15828,7 +15828,7 @@ const App = () => {
|
||||
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) {}
|
||||
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), live: true }); } catch (e) {}
|
||||
});
|
||||
} else if (window.SonicSF) {
|
||||
var allTracks = activeTracksRef.current || [];
|
||||
@@ -15911,7 +15911,7 @@ const App = () => {
|
||||
}
|
||||
}
|
||||
} 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) {}
|
||||
try { window.SonicMidiRouter.pushEvent({ cmd: 'NOTE_OFF', channel: bst.id, pitch: pitch, velocity: 0, percussion: !!(bst.synth_engine && bst.synth_engine.soundfont_bank === 128), live: true }); } catch (e) {}
|
||||
});
|
||||
} else if (window.SonicSF && window.SonicSF.stopNote) {
|
||||
var stopTracks = activeTracksRef.current || [];
|
||||
@@ -21853,9 +21853,9 @@ const App = () => {
|
||||
const isPerc = !!(track && track.synth_engine && track.synth_engine.soundfont_bank === 128);
|
||||
const tch = track ? track.id : 0;
|
||||
try { if (window.__ensureBridgeProgram) window.__ensureBridgeProgram(tch, program, track && track.synth_engine); } catch (e) {}
|
||||
try { window.SonicMidiRouter.pushEvent({ cmd: 'NOTE_ON', channel: tch, pitch: pitch || 60, velocity: velocity, percussion: isPerc }); } catch (e) {}
|
||||
try { window.SonicMidiRouter.pushEvent({ cmd: 'NOTE_ON', channel: tch, pitch: pitch || 60, velocity: velocity, percussion: isPerc, live: true }); } catch (e) {}
|
||||
setTimeout(function () {
|
||||
try { window.SonicMidiRouter.pushEvent({ cmd: 'NOTE_OFF', channel: tch, pitch: pitch || 60, velocity: 0, percussion: isPerc }); } catch (e) {}
|
||||
try { window.SonicMidiRouter.pushEvent({ cmd: 'NOTE_OFF', channel: tch, pitch: pitch || 60, velocity: 0, percussion: isPerc, live: true }); } catch (e) {}
|
||||
}, (durationMs || 500) + 30);
|
||||
return;
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -110,7 +110,7 @@
|
||||
* velocity 0..1; sampleOffset in samples within the current audio block.
|
||||
* data2/data3 (A12): CC value / program / PB LSB|MSB.
|
||||
*/
|
||||
dispatchMidiEvent: function (cmd, channel, pitch, velocity, sampleOffset, data2, data3) {
|
||||
dispatchMidiEvent: function (cmd, channel, pitch, velocity, sampleOffset, data2, data3, live) {
|
||||
if (!this._tauri()) return false;
|
||||
var safeVelocity = Math.floor(Math.min(1.0, Math.max(0.0, velocity)) * 127);
|
||||
var byteCmd;
|
||||
@@ -127,7 +127,8 @@
|
||||
velocity: safeVelocity,
|
||||
data2: data2 === undefined ? 0 : data2,
|
||||
data3: data3 === undefined ? 0 : data3,
|
||||
sampleOffset: sampleOffset || 0
|
||||
sampleOffset: sampleOffset || 0,
|
||||
live: !!live
|
||||
}).catch(function (e) { console.warn('[BridgeService] push_midi_event:', e); });
|
||||
return true;
|
||||
},
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
if (typeof ch === 'string') ch = this.allocateChannel(ch, opts.percussion);
|
||||
if (ch === undefined || ch === null) ch = 0;
|
||||
if (this.isBridgeActive()) {
|
||||
window.NativeBridgeService.dispatchMidiEvent(cmd, ch, pitch, vel, sampleOffset, opts.data2, opts.data3);
|
||||
window.NativeBridgeService.dispatchMidiEvent(cmd, ch, pitch, vel, sampleOffset, opts.data2, opts.data3, opts.live);
|
||||
return;
|
||||
}
|
||||
if (this.onFallback) this.onFallback(cmd, ch, pitch, vel);
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -32,7 +32,7 @@ struct SharedAudioBufferIPC {
|
||||
uint8_t velocity; // 0-127 (0x9 + vel=0 == note off)
|
||||
uint8_t data2; // CC value / program number / PB LSB
|
||||
uint8_t data3; // PB MSB (0xE only)
|
||||
uint8_t reserved[2]; // explicit padding — keeps C/Rust layout stable
|
||||
uint8_t reserved[2]; // reserved[0]: live flag (1 = live input, bypass transportStopped guard); reserved[1]: 0 — keeps C/Rust layout stable
|
||||
uint32_t sampleOffset;
|
||||
} midiQueue[64];
|
||||
|
||||
|
||||
+1413
-1412
File diff suppressed because it is too large
Load Diff
@@ -667,11 +667,12 @@ fn push_midi_event(
|
||||
data2: u8,
|
||||
data3: u8,
|
||||
sample_offset: u32,
|
||||
live: bool,
|
||||
) -> Result<(), String> {
|
||||
let state = app.state::<ShmState>();
|
||||
let guard = state.0.lock().map_err(|e| e.to_string())?;
|
||||
let shm = guard.as_ref().ok_or("bridge shm unavailable")?;
|
||||
shm.push_midi(command, channel, pitch, velocity, data2, data3, sample_offset)
|
||||
shm.push_midi(command, channel, pitch, velocity, data2, data3, sample_offset, live as u8)
|
||||
.then_some(())
|
||||
.ok_or_else(|| "midi queue full".to_string())
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ pub struct MidiEventIPC {
|
||||
pub velocity: u8,
|
||||
pub data2: u8, // CC value / program / PB LSB
|
||||
pub data3: u8, // PB MSB (0xE only)
|
||||
pub reserved: [u8; 2],
|
||||
pub reserved: [u8; 2], // reserved[0]: live flag (1=live input, bypass transportStopped guard); reserved[1]: 0
|
||||
pub sample_offset: u32,
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ impl Shm {
|
||||
unsafe { &mut *self.view }
|
||||
}
|
||||
|
||||
pub fn push_midi(&self, cmd: u8, channel: u8, pitch: u8, velocity: u8, data2: u8, data3: u8, sample_offset: u32) -> bool {
|
||||
pub fn push_midi(&self, cmd: u8, channel: u8, pitch: u8, velocity: u8, data2: u8, data3: u8, sample_offset: u32, live: u8) -> bool {
|
||||
let ipc = self.ipc();
|
||||
if ipc.midi_queue_count as usize >= MIDI_QUEUE_CAP {
|
||||
return false;
|
||||
@@ -125,7 +125,7 @@ impl Shm {
|
||||
velocity,
|
||||
data2,
|
||||
data3,
|
||||
reserved: [0u8; 2],
|
||||
reserved: [live, 0u8],
|
||||
sample_offset,
|
||||
};
|
||||
ipc.midi_queue_count += 1;
|
||||
|
||||
Reference in New Issue
Block a user