them big_tasks.md (roadmap G0-G4, danh dau G1.1-G1.5 hoan thanh) + debug scripts/probes cua phien lam viec G0.1-G1.5 (test_g13/test_g12/test_g15_stress, patch_g1x, deploy/build bridge, probe_g0x)

This commit is contained in:
2026-08-15 21:59:17 +07:00
parent c813481357
commit 3664ffbc47
46 changed files with 4614 additions and 0 deletions
+97
View File
@@ -0,0 +1,97 @@
# G1.4: bo mute-when-editor-open — xoa editorOpen machinery (channelQuiet chi con reloading)
import io, sys
p = 'native_bridge/src/main.cpp'
raw = open(p, 'rb').read()
EM = b'\xe2\x80\x94'
NL = b'\r\n'
def rep(old, new, tag):
global raw
o = old.replace(b'\n', NL)
if o not in raw:
print(f'MISSING [{tag}]')
sys.exit(1)
raw = raw.replace(o, new.replace(b'\n', NL))
print(f'OK [{tag}]')
rep(b"""// Editor-open tracking: while a channel's VST editor (native window) is
// attached, EVERY channel assigned the same plugin DLL path must stay quiet """ + EM + b"""
// the plugin's window proc runs on the editor channel's worker while the
// audio loop calls process() on other instances of the same DLL (2 threads
// in one DLL -> Nexus USER32 crash). g_editorPathCount = refcount per
// lowercase plugin path; g_editorOpenPath/g_editorOpen per channel.
// Lock order: g_editorMutex is taken while holding the engine mutex
// (channelQuiet) or standalone in non-rt jobs """ + EM + b""" never the reverse.
static std::mutex g_editorMutex;
static std::map<std::string, int> g_editorPathCount;
static std::string g_editorOpenPath[16];
static bool g_editorOpen[16] = { false };
""", b"", "decl-block")
rep(b"""// Editor closed / instrument replaced: drop the channel's editor-open state
// (refcounted per lowercase plugin path). Called from non-rt jobs only """ + EM + b"""
// never from the audio loop.
static void clear_editor_open(uint32_t ch) {
std::lock_guard<std::mutex> lk(g_editorMutex);
if (!g_editorOpen[ch]) return;
g_editorOpen[ch] = false;
std::string pth = g_editorOpenPath[ch];
g_editorOpenPath[ch].clear();
if (!pth.empty()) {
auto it = g_editorPathCount.find(pth);
if (it != g_editorPathCount.end() && --it->second <= 0)
g_editorPathCount.erase(it);
}
}
""", b"", "clear_editor_open")
rep(b""" // Editor-open predicate: channelQuiet() checks whether ANY editor is
// attached for the channel's plugin DLL path (refcounted in
// g_editorPathCount, updated by the open/close GUI jobs).
instruments.setEditorOpenPredicate([](const std::string& lp) {
std::lock_guard<std::mutex> lk(g_editorMutex);
auto it = g_editorPathCount.find(lp);
return it != g_editorPathCount.end() && it->second > 0;
});
""", b"", "set-predicate")
rep(b""" // Editor attached: mark the plugin path editor-open so the
// audio loop stops processing EVERY channel assigned this
// DLL while the editor lives (its window proc runs on this
// worker; process() elsewhere on the same DLL -> Nexus crash).
{
std::lock_guard<std::mutex> lk(g_editorMutex);
if (!gp.empty()) {
g_editorOpen[guiCh] = true;
g_editorOpenPath[guiCh] = gp;
++g_editorPathCount[gp];
}
}
disable_ime_contexts((HWND)hwnd);
""", b""" disable_ime_contexts((HWND)hwnd);
""", "attach-mark")
rep(b""" // Editor detached + fresh instance loaded: drop editor-open
// state (channelQuiet falls back to reloading flags only).
clear_editor_open(ch);
""", b"", "close-ok-path")
rep(b""" // Instrument already gone (unloaded) """ + EM + b""" nothing to rebuild.
g_engine->setReloading(ch, false);
clear_editor_open(ch);
""", b""" // Instrument already gone (unloaded) """ + EM + b""" nothing to rebuild.
g_engine->setReloading(ch, false);
""", "close-else-path")
rep(b""" ShowWindow(hToHide, SW_HIDE);
// Editor detached: drop editor-open state before the
// instrument is replaced (assign).
clear_editor_open(ch);
""", b""" ShowWindow(hToHide, SW_HIDE);
""", "load-close-path")
open(p, 'wb').write(raw)
print('DONE main.cpp')