98 lines
4.1 KiB
Python
98 lines
4.1 KiB
Python
# 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')
|