feat(vst-gui): open VST3 GUI while playing (level 1)
- main.cpp: drop transportStopped defer in handleOpenGui (G0.1 legacy); G0.1b setReloading-before-job + single UiThread (G1.2) block the 2-thread-1-DLL race. GUI opens immediately during PLAY, short mute (~0.1-0.3s first time, hasAttachedOnce_ false so reloadForGUI skips reload); notes already sounding are kept. Reopen after close still reloads (1-3s mute) - level 2 not feasible. - app.jsx: remove !isPlayingRef.current guard before openNativeGUI in loadTrackInstrumentToBridge. - rebuild app.precompiled.js + daw_vst_bridge.exe.
This commit is contained in:
@@ -15632,11 +15632,11 @@ 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).
|
||||
// SF→VSTi BUG 2026-08-13: GUI mở → C++ mute channel tới khi đóng GUI →
|
||||
// đang play thì âm tắt ngay (reloading_=true, note-on drop). Khi đang
|
||||
// play chỉ load instrument im lặng; GUI mở qua nút GUI riêng
|
||||
// (ensureAndOpenVstGui) — không tự mở giữa lúc phát.
|
||||
if (ok && btype === 'VST3' && !isPlayingRef.current && window.NativeBridgeService.openNativeGUI) {
|
||||
// LEVEL-1 (2026-08-15): mở GUI ngay cả khi đang play. C++ đã bỏ defer
|
||||
// transport STOP; setReloading trước job (G0.1b) + 1 UiThread (G1.2)
|
||||
// chặn race 2 thread 1 DLL. Mute ngắn ~0.1-0.3s lần đầu, note đang
|
||||
// ngân không mất. Reopen sau khi đóng vẫn mute 1-3s (reload) — level 2.
|
||||
if (ok && btype === 'VST3' && window.NativeBridgeService.openNativeGUI) {
|
||||
try { await openVstGuiRetry(instrumentId, bch, 20); } catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -823,11 +823,11 @@ if(isSf&&window.__bridgeLoadedChannels)delete window.__bridgeLoadedChannels[bch]
|
||||
// phải gửi lại program change để ra ĐÚNG instrument.
|
||||
if(ok&&window.__bridgeLastProgram){const _pfx=trackId+':';Object.keys(window.__bridgeLastProgram).forEach(k=>{if(k.indexOf(_pfx)===0)delete window.__bridgeLastProgram[k];});}if(ok){if(!window.__bridgeLoadedChannels)window.__bridgeLoadedChannels={};window.__bridgeLoadedChannels[bch]=true;}if(ok&&btype==='VST3'&&p){try{if(!window.__bridgePluginPaths)window.__bridgePluginPaths={};window.__bridgePluginPaths[instrumentId]=p;updateActiveTracks(prev=>prev.map(t=>t.id===trackId?{...t,synth_engine:{...(t.synth_engine||{}),plugin_path:p}}:t));}catch(e){}}// 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).
|
||||
// SF→VSTi BUG 2026-08-13: GUI mở → C++ mute channel tới khi đóng GUI →
|
||||
// đang play thì âm tắt ngay (reloading_=true, note-on drop). Khi đang
|
||||
// play chỉ load instrument im lặng; GUI mở qua nút GUI riêng
|
||||
// (ensureAndOpenVstGui) — không tự mở giữa lúc phát.
|
||||
if(ok&&btype==='VST3'&&!isPlayingRef.current&&window.NativeBridgeService.openNativeGUI){try{await openVstGuiRetry(instrumentId,bch,20);}catch(e){}}}})();};const setTrackInstrumentWithProgram=(trackId,instrumentId,programNumber,displayName,bankNumber)=>{const isSfInstrument=instrumentId&&typeof instrumentId==='string'&&instrumentId.startsWith('sf_');const sfBank=bankNumber!==undefined?bankNumber:isSfInstrument?0:undefined;const sfProg=programNumber!==undefined?programNumber:undefined;var mt=activeTracksRef.current||tracks;var curTrk=null;for(var ci=0;ci<mt.length;ci++){if(mt[ci].id===trackId){curTrk=mt[ci];break;}}// ── Unload Carla bridge khi chuyển từ VSTi sang instrument KHÔNG phải VST ──
|
||||
// LEVEL-1 (2026-08-15): mở GUI ngay cả khi đang play. C++ đã bỏ defer
|
||||
// transport STOP; setReloading trước job (G0.1b) + 1 UiThread (G1.2)
|
||||
// chặn race 2 thread 1 DLL. Mute ngắn ~0.1-0.3s lần đầu, note đang
|
||||
// ngân không mất. Reopen sau khi đóng vẫn mute 1-3s (reload) — level 2.
|
||||
if(ok&&btype==='VST3'&&window.NativeBridgeService.openNativeGUI){try{await openVstGuiRetry(instrumentId,bch,20);}catch(e){}}}})();};const setTrackInstrumentWithProgram=(trackId,instrumentId,programNumber,displayName,bankNumber)=>{const isSfInstrument=instrumentId&&typeof instrumentId==='string'&&instrumentId.startsWith('sf_');const sfBank=bankNumber!==undefined?bankNumber:isSfInstrument?0:undefined;const sfProg=programNumber!==undefined?programNumber:undefined;var mt=activeTracksRef.current||tracks;var curTrk=null;for(var ci=0;ci<mt.length;ci++){if(mt[ci].id===trackId){curTrk=mt[ci];break;}}// ── Unload Carla bridge khi chuyển từ VSTi sang instrument KHÔNG phải VST ──
|
||||
// (soundfont/GM/default). Nếu không, Carla vẫn chạy với VSTi cũ → MIDI vẫn
|
||||
// play qua Carla bridge (âm sai instrument + âm kẹt không dừng được).
|
||||
try{const _hasInst=!!instrumentId;const _wasVst=curTrk&&curTrk.synth_engine&&String(curTrk.synth_engine.type||'').indexOf('vst')!==-1;const _nowVst=_hasInst&&!isSfInstrument;if(_wasVst&&!_nowVst&&window.SonicCarlaMidi&&window.SonicCarlaMidi.stopBridge){window.SonicCarlaMidi.stopBridge();try{if(window.SonicMidiRouter)window.SonicMidiRouter.panic();else if(window.SonicSF&&window.SonicSF.stopAll)window.SonicSF.stopAll();}catch(e){}stopAllNativeSfNotes();console.log('[Instrument] Carla bridge unloaded — track',trackId,'switched from VSTi to non-VST');}}catch(e){console.warn('[Instrument] carla-stop on instrument switch error:',e);}var mch=curTrk?assignTrackMidiChannel(curTrk,mt):sfBank===128?9:0;updateActiveTracks(prev=>prev.map(t=>{if(t.id!==trackId)return t;const hasInstrument=!!instrumentId;const instrType=isSfInstrument?'soundfont':hasInstrument?'vst3':'default';const synthEngine=hasInstrument?{type:instrType,plugin_id:instrumentId,soundfont_bank:sfBank!==undefined?sfBank:0,soundfont_program:sfProg!==undefined?sfProg:0,soundfont_id:isSfInstrument?instrumentId.replace('sf_',''):''}:undefined;return{...t,midiChannel:mch,instrumentId,instrumentProgram:sfProg,instrumentName:displayName,soundfont_bank:sfBank,soundfont_program:sfProg,synth_engine:synthEngine,type:hasInstrument?'MIDI':t.type==='MIDI'?'audio':t.type};}));setInstrumentDropdownTrackId(null);setInstrumentDropdownBtnRect(null);setSynthCategory(null);// Trigger FluidSynth load + program change when soundfont instrument selected
|
||||
|
||||
Binary file not shown.
@@ -796,19 +796,14 @@ int main(int argc, char* argv[]) {
|
||||
})) {
|
||||
return;
|
||||
}
|
||||
// G0.1 (BUG_REPORT): mo GUI khi dang PLAY -> attachView chay tren worker
|
||||
// thread trong luc audio loop process() cung DLL (2 thread 1 plugin) ->
|
||||
// Nexus throw (createView/attached) -> GUI khong load + retry spam ->
|
||||
// stall 3s -> watchdog kill bridge -> mat het instrument -> cam. Defer
|
||||
// OPEN_GUI toi khi transport STOP (sweep duoi fulfill khi loaded &&
|
||||
// transportStopped). Khong doi: tranh mat am; user STOP la GUI tu mo.
|
||||
if (!transportStopped) {
|
||||
std::cerr << "[NativeBridge] GUI deferred ch=" << guiCh
|
||||
<< " plugin=" << pluginId << " (transport PLAY) - queued" << std::endl;
|
||||
std::lock_guard<std::mutex> lock(g_pendingGuiMutex);
|
||||
g_pendingGui[guiCh] = { (void*)arg1, pluginId };
|
||||
return;
|
||||
}
|
||||
// G0.1 (historical): mo GUI khi dang PLAY bi defer toi khi STOP vi 2
|
||||
// thread 1 plugin (audio loop process + attach worker) -> Nexus throw.
|
||||
// LEVEL-1 (2026-08-15): bo defer. G0.1b (setReloading tren MAIN thread
|
||||
// truoc job, o duoi) da silence same-path channels va G1.2 (1 UiThread,
|
||||
// audio loop khong pump window messages) chan race 2 thread 1 DLL.
|
||||
// GUI mo ngay khi play; mute ngan (~0.1-0.3s lan dau: hasAttachedOnce_
|
||||
// false nen reloadForGUI khong reload, Vst3Instrument.cpp 688). Note
|
||||
// dang ngan khong mat. Reopen sau khi dong VAN reload (1-3s mute).
|
||||
// G1.2: window + attach chay tren UiThread (1 thread chung, COM STA +
|
||||
// message pump + job queue). Window messages do UiThread pump dispatch —
|
||||
// audio loop khong con PeekMessageW (xoa block pump o main loop).
|
||||
|
||||
Reference in New Issue
Block a user