import subprocess def load(p): return open(p, encoding='utf-8', newline='').read() def save(p, s): open(p, 'w', encoding='utf-8', newline='').write(s) def rep(s, needle, repl, tag): n = s.count(needle) if n != 1: raise SystemExit("FAIL %s: needle count=%d" % (tag, n)) return s.replace(needle, repl) cr = '\r\n' # ---- main.cpp ---- mp = load('native_bridge/src/main.cpp') mp = rep(mp, "int main(int argc, char* argv[]) {" + cr + " std::cout << \"[NativeBridge] Starting DAW Host Bridge Engine...\" << std::endl;" + cr + "#ifdef _WIN32" + cr + " CoInitializeEx(nullptr, COINIT_MULTITHREADED);" + cr + cr + " // Disable Power Throttling (Efficiency Mode) for this background process", "int main(int argc, char* argv[]) {" + cr + " std::cout << \"[NativeBridge] Starting DAW Host Bridge Engine...\" << std::endl;" + cr + "#ifdef _WIN32" + cr + " // Disable Power Throttling (Efficiency Mode) for this background process", "coinit") mp = rep(mp, " SetProcessInformation(GetCurrentProcess(), ProcessPowerThrottling, &powerState, sizeof(powerState));" + cr + cr + " // Elevate main audio processing thread to time-critical priority" + cr + " SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);", " SetProcessInformation(GetCurrentProcess(), ProcessPowerThrottling, &powerState, sizeof(powerState));", "timecritical") mp = rep(mp, " instruments.setEditorOpenPredicate([](const std::string& /*lp*/) {" + cr + " return false;" + cr + " });", " instruments.setEditorOpenPredicate([](const std::string& lp) {" + cr + " std::lock_guard lk(g_editorMutex);" + cr + " auto it = g_editorPathCount.find(lp);" + cr + " return it != g_editorPathCount.end() && it->second > 0;" + cr + " });", "predicate") blob = subprocess.check_output(['git', 'show', '0cec3d3:native_bridge/src/main.cpp']).decode('utf-8') if '\r\n' not in blob and '\n' in blob: blob = blob.replace('\n', '\r\n') def fn_start(s): i = s.find('static void post_close_gui(uint32_t ch, HWND hwnd) {' + cr + ' ChannelWorker* w = nullptr;') if i < 0: i = s.find('static void post_close_gui(uint32_t ch, HWND hwnd) {\n ChannelWorker* w = nullptr;') if i < 0: raise SystemExit("fn_start not found") return i cur_start = fn_start(mp) cur_end = mp.find('int main(int argc, char* argv[]) {', cur_start) old_start = fn_start(blob) old_end = blob.find('int main(int argc, char* argv[]) {', old_start) mp = rep(mp, mp[cur_start:cur_end], blob[old_start:old_end], "post_close_gui") needle5 = ( " workers[guiCh]->post([&instruments, guiCh, arg1, arg2 = pluginId]() {" + cr + " if (!instruments.get(guiCh)) {" + cr + " std::cerr << \"[NativeBridge] GUI attach FAILED hwnd=\" << (void*)arg1" + cr + " << \" plugin=\" << arg2 << \" ch=\" << guiCh << \" (no instrument loaded)\" << std::endl;" + cr + " return;" + cr + " }" + cr + " if (auto* inst0 = instruments.get(guiCh)) {" + cr + " if (inst0->hasAttachedView()) {" + cr + " return;" + cr + " }" + cr + " }" + cr + " void* hwnd = (void*)arg1;" + cr + "#ifdef _WIN32" + cr + " HWND nativeHwnd = nullptr;" + cr + " {" + cr + " std::lock_guard lock(g_guiMutex);" + cr + " auto it = g_guiWindows.find(guiCh);" + cr + " if (it != g_guiWindows.end()) nativeHwnd = (HWND)it->second;" + cr + " }" + cr + " if (hwnd == 0) {" + cr + " if (nativeHwnd && IsWindow(nativeHwnd)) {" + cr + " hwnd = (void*)nativeHwnd;" + cr + " SetWindowTextA(nativeHwnd, arg2.c_str());" + cr + " ShowWindow(nativeHwnd, SW_SHOW);" + cr + " SetForegroundWindow(nativeHwnd);" + cr + " // Reuse: cap nhat USERDATA (channel+1) - inst CU da bi thay" + cr + " // the boi assign() -> WM_DESTROY sau nay lookup inst MOI." + cr + " SetWindowLongPtrA(nativeHwnd, GWLP_USERDATA, (LONG_PTR)(guiCh + 1));" + cr + " } else {" + cr + " nativeHwnd = (HWND)create_native_vst_window(arg2.c_str());" + cr + " if (!nativeHwnd) {" + cr + " std::cerr << \"[NativeBridge] GUI create window FAILED plugin=\" << arg2 << std::endl;" + cr + " return;" + cr + " }" + cr + " {" + cr + " std::lock_guard lock(g_guiMutex);" + cr + " g_guiWindows[guiCh] = nativeHwnd; // keep window alive" + cr + " g_hwndToCh[nativeHwnd] = guiCh; // WM_DESTROY cleanup" + cr + " }" + cr + " SetWindowLongPtrA(nativeHwnd, GWLP_USERDATA, (LONG_PTR)(guiCh + 1));" + cr + " hwnd = (void*)nativeHwnd;" + cr + " }" + cr + " }" + cr + "#endif" + cr + " if (auto* inst0 = instruments.get(guiCh)) {" + cr + " if (inst0->hasAttachedView()) {" + cr + " return;" + cr + " }" + cr + " }" + cr + "#ifdef _WIN32" + cr + " // Option B: chi 1 editor VST mo tai 1 thoi diem toan" ) repl5 = ( " void* hwnd = (void*)arg1;" + cr + "#ifdef _WIN32" + cr + " // Window PHAI thuoc MAIN thread (audio loop pump nay dispatch" + cr + " // messages cua no moi vong lap). Tao/cap nhat window ngay tai day." + cr + " HWND nativeHwnd = nullptr;" + cr + " {" + cr + " std::lock_guard lock(g_guiMutex);" + cr + " auto it = g_guiWindows.find(guiCh);" + cr + " if (it != g_guiWindows.end()) nativeHwnd = (HWND)it->second;" + cr + " }" + cr + " if (hwnd == 0) {" + cr + " if (nativeHwnd && IsWindow(nativeHwnd)) {" + cr + " hwnd = (void*)nativeHwnd;" + cr + " SetWindowTextA(nativeHwnd, pluginId.c_str());" + cr + " ShowWindow(nativeHwnd, SW_SHOW);" + cr + " SetForegroundWindow(nativeHwnd);" + cr + " // Reuse: cap nhat USERDATA (channel+1) - inst CU da bi thay" + cr + " // the boi assign() -> WM_DESTROY sau nay lookup inst MOI." + cr + " SetWindowLongPtrA(nativeHwnd, GWLP_USERDATA, (LONG_PTR)(guiCh + 1));" + cr + " } else {" + cr + " nativeHwnd = (HWND)create_native_vst_window(pluginId.c_str());" + cr + " if (!nativeHwnd) {" + cr + " std::cerr << \"[NativeBridge] GUI create window FAILED plugin=\" << pluginId << std::endl;" + cr + " return;" + cr + " }" + cr + " {" + cr + " std::lock_guard lock(g_guiMutex);" + cr + " g_guiWindows[guiCh] = nativeHwnd; // keep window alive" + cr + " g_hwndToCh[nativeHwnd] = guiCh; // WM_DESTROY cleanup" + cr + " }" + cr + " SetWindowLongPtrA(nativeHwnd, GWLP_USERDATA, (LONG_PTR)(guiCh + 1));" + cr + " hwnd = (void*)nativeHwnd;" + cr + " }" + cr + " }" + cr + "#endif" + cr + " workers[guiCh]->post([&instruments, guiCh, hwnd, arg2 = pluginId]() {" + cr + " if (!instruments.get(guiCh)) {" + cr + " std::cerr << \"[NativeBridge] GUI attach FAILED hwnd=\" << hwnd" + cr + " << \" plugin=\" << arg2 << \" ch=\" << guiCh << \" (no instrument loaded)\" << std::endl;" + cr + " return;" + cr + " }" + cr + " if (auto* inst0 = instruments.get(guiCh)) {" + cr + " if (inst0->hasAttachedView()) {" + cr + " return;" + cr + " }" + cr + " }" + cr + "#ifdef _WIN32" + cr + " // Option B: chi 1 editor VST mo tai 1 thoi diem toan" ) mp = rep(mp, needle5, repl5, "handleOpenGui-window") mp = rep(mp, " try {" + cr + " instruments.setBypassed(true);" + cr + " sleep_ms(10);" + cr + " ok = inst->reloadForGUI();" + cr + " instruments.setBypassed(false);" + cr + " // IME recursion fix: strip the editor's IMC before", " try {" + cr + " ok = inst->reloadForGUI();" + cr + " // IME recursion fix: strip the editor's IMC before", "bypass-open1") mp = rep(mp, " } catch (...) {" + cr + " instruments.setBypassed(false);" + cr + " std::cerr << \"[NativeBridge] GUI attach EXCEPTION ch=\" << guiCh", " } catch (...) {" + cr + " std::cerr << \"[NativeBridge] GUI attach EXCEPTION ch=\" << guiCh", "bypass-open2") mp = rep(mp, ' << " (channel active with editor open)" << std::endl;', ' << " (channel muted while editor open)" << std::endl;', "logmsg") mp = rep(mp, " if (ch != UINT32_MAX && g_engine) {" + cr + " auto* inst = g_engine->get(ch);" + cr + " if (inst) {" + cr + " inst->resizeView(w, h);" + cr + " }" + cr + " }" + cr + " return 0;", " if (ch != UINT32_MAX && g_workers) {" + cr + " auto wit = g_workers->find(ch);" + cr + " if (wit != g_workers->end()) {" + cr + " // onSize() must run on the channel worker (the view was attached" + cr + " // in its COM STA apartment), not on the main pump thread." + cr + " wit->second->post([ch, w, h]() {" + cr + " if (!g_engine) return;" + cr + " auto* i = g_engine->get(ch);" + cr + " if (i) i->resizeView(w, h);" + cr + " });" + cr + " }" + cr + " }" + cr + " return 0;", "wmsize") save('native_bridge/src/main.cpp', mp) # ---- Vst3Instrument.cpp ---- vp = load('native_bridge/src/Vst3Instrument.cpp') vp = rep(vp, "bool Vst3Instrument::reloadForGUI() {" + cr + "#ifndef HAVE_VST3SDK" + cr + " return false;" + cr + "#else" + cr + " auto* s = static_cast(state_);" + cr + " if (!s || !s->controller) return false;" + cr + " return true;" + cr + "#endif" + cr + "}", "bool Vst3Instrument::reloadForGUI() {" + cr + "#ifndef HAVE_VST3SDK" + cr + " return false;" + cr + "#else" + cr + " auto* s = static_cast(state_);" + cr + " if (!s || !s->controller) return false;" + cr + " if (s->view && guiAttached_) return true;" + cr + " if (hasAttachedOnce_ && !guiAttached_) {" + cr + " // Reopen GUI sau khi dong: mot so plugin (Nexus...) hang o" + cr + " // view->attached() LAN 2 tren cung component instance. Tao lai inst" + cr + " // moi tren CUNG worker thread (COM STA con song) roi attach lai." + cr + " // PHAN NAY PHAI chay tren worker thread — apartment cua channel song" + cr + " // o day; chay tren thread tam thi apartment moi chet ngay sau do" + cr + " // (reopen lan sau -> treo nhu bridge_like)." + cr + " if (!reload()) return false;" + cr + " s = static_cast(state_);" + cr + " if (!s || !s->controller) return false;" + cr + " }" + cr + " return true;" + cr + "#endif" + cr + "}", "reloadForGUI") vp = rep(vp, "void Vst3Instrument::closeGUI() {" + cr + "#ifndef HAVE_VST3SDK" + cr + " return;" + cr + "#else" + cr + " auto* s = static_cast(state_);" + cr + " if (s && s->view) {" + cr + " if (guiAttached_) {" + cr + " try {" + cr + " s->view->removed();" + cr + " } catch (...) {" + cr + " std::cerr << \"[Vst3Instrument] Exception inside view->removed()\" << std::endl;" + cr + " }" + cr + " }" + cr + " s->view = nullptr;" + cr + " }" + cr + " guiAttached_ = false;" + cr + "#endif" + cr + "}", "void Vst3Instrument::closeGUI() {" + cr + "#ifndef HAVE_VST3SDK" + cr + " return;" + cr + "#else" + cr + " auto* s = static_cast(state_);" + cr + " // Do NOT call s->view->removed(): Nexus's removed() enters an internal" + cr + " // modal wait for a message only this thread's message pump can dispatch" + cr + " // — but this thread is inside removed(), so it deadlocks forever" + cr + " // (observed: closeGUI job never returns; wdisp flood from the editor)." + cr + " // Nulling the view and letting the next terminate() (reload / destructor)" + cr + " // tear the editor windows down on this same thread is the deterministic" + cr + " // path out. Callers (post_close_gui / load job) additionally destroy the" + cr + " // editor's child windows right here on this thread so the plugin stops" + cr + " // pumping; the leaked editor object is inert once its windows are gone." + cr + " if (s) s->view = nullptr;" + cr + " guiAttached_ = false;" + cr + "#endif" + cr + "}", "closeGUI") save('native_bridge/src/Vst3Instrument.cpp', vp) print("ALL EDITS OK")