fix crash bridge khi đổi SF→VSTi đang play: silence same-plugin theo path MỚI trước assign() (createInstance) — track restore giữ cùng DLL process song song audio loop = 2 threads 1 DLL Nexus crash; không tự mở GUI khi đang play (C++ mute channel tới khi đóng GUI → tắt âm)
This commit is contained in:
+32
-18
@@ -227,13 +227,16 @@ private:
|
||||
// Two threads inside one VST3 DLL (Nexus) crash/deadlock: the audio loop's
|
||||
// process() on one instance must not race createInstance/createView/terminate
|
||||
// on another. Windows plugin paths are case-insensitive — compare lowercased.
|
||||
static std::string lower_plugin_path(uint32_t ch) {
|
||||
std::string p = g_engine ? g_engine->pathOf(ch) : std::string();
|
||||
static std::string lower_path_str(std::string p) {
|
||||
std::transform(p.begin(), p.end(), p.begin(),
|
||||
[](unsigned char c) { return (char)::tolower(c); });
|
||||
return p;
|
||||
}
|
||||
|
||||
static std::string lower_plugin_path(uint32_t ch) {
|
||||
return g_engine ? lower_path_str(g_engine->pathOf(ch)) : std::string();
|
||||
}
|
||||
|
||||
// Channels (other than ch) currently assigned the same plugin DLL path.
|
||||
static std::vector<uint32_t> same_plugin_channels(uint32_t ch) {
|
||||
std::vector<uint32_t> out;
|
||||
@@ -820,8 +823,14 @@ int main(int argc, char* argv[]) {
|
||||
// session-restore instances). Silence this channel (its old
|
||||
// instance is being torn down / replaced) and every
|
||||
// same-plugin channel for the whole job. Old path covers
|
||||
// the old-instance teardown; the new path (after assign)
|
||||
// covers the freshly created instance.
|
||||
// the old-instance teardown; the new path (computed BEFORE
|
||||
// assign — see spNew below) covers the freshly created
|
||||
// instance. CRASH FIX (SF→VSTi while playing): the new
|
||||
// path must be silenced BEFORE assign() — assign() itself
|
||||
// runs createInstance (loadPlugin) on this worker, and a
|
||||
// restored channel on ANOTHER track holding the SAME DLL
|
||||
// kept process()ing on the audio loop during that window
|
||||
// (old code silenced spNew only AFTER assign → crash).
|
||||
instruments.setReloading(ch, true);
|
||||
std::vector<uint32_t> spOld = same_plugin_channels(ch);
|
||||
for (uint32_t y : spOld) {
|
||||
@@ -829,6 +838,24 @@ int main(int argc, char* argv[]) {
|
||||
std::cerr << "[dbg] load: silenced same-plugin ch=" << y
|
||||
<< " during load ch=" << ch << std::endl;
|
||||
}
|
||||
// Channels (other than ch) already assigned the NEW path —
|
||||
// silence BEFORE createInstance enters that DLL.
|
||||
std::vector<uint32_t> spNew;
|
||||
if (t == InstrumentType::VST3) {
|
||||
std::string np = lower_path_str(path);
|
||||
if (!np.empty()) {
|
||||
for (uint32_t y = 0; y < 16; ++y) {
|
||||
if (y == ch) continue;
|
||||
if (!g_engine->get(y)) continue;
|
||||
if (std::find(spOld.begin(), spOld.end(), y) != spOld.end()) continue;
|
||||
if (lower_plugin_path(y) != np) continue;
|
||||
g_engine->setReloading(y, true);
|
||||
spNew.push_back(y);
|
||||
std::cerr << "[dbg] load: silenced same-plugin (new path) ch=" << y
|
||||
<< " during load ch=" << ch << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef _WIN32
|
||||
// DONG cua so editor dang mo cua channel TRUOC khi assign():
|
||||
// thay the inst (VST3 -> SF2/inst khac) ma editor con song ->
|
||||
@@ -879,25 +906,12 @@ int main(int argc, char* argv[]) {
|
||||
std::cerr << "[NativeBridge] instrument load FAILED ch=" << ch
|
||||
<< " type=" << (int)t << " " << path << std::endl;
|
||||
}
|
||||
// New-path channels (the freshly created instance's DLL) —
|
||||
// silence any not already covered by the old path.
|
||||
std::vector<uint32_t> spNew;
|
||||
if (ok) spNew = same_plugin_channels(ch);
|
||||
for (uint32_t y : spNew) {
|
||||
if (std::find(spOld.begin(), spOld.end(), y) == spOld.end()) {
|
||||
g_engine->setReloading(y, true);
|
||||
std::cerr << "[dbg] load: silenced same-plugin ch=" << y
|
||||
<< " (new path) during load ch=" << ch << std::endl;
|
||||
}
|
||||
}
|
||||
// Restore. Failed load keeps the OLD instance — unmute it
|
||||
// back (silenced at job start); a successful assign leaves
|
||||
// the fresh instance unmuted by construction.
|
||||
if (!ok) g_engine->setReloading(ch, false);
|
||||
for (uint32_t y : spOld) unmute_if_not_closing(y, "load");
|
||||
for (uint32_t y : spNew)
|
||||
if (std::find(spOld.begin(), spOld.end(), y) == spOld.end())
|
||||
unmute_if_not_closing(y, "load");
|
||||
for (uint32_t y : spNew) unmute_if_not_closing(y, "load");
|
||||
});
|
||||
} else if (c.type == 1) { // PANIC
|
||||
instruments.allNotesOff();
|
||||
|
||||
Reference in New Issue
Block a user