fix crash daw_vst_bridge 0xc000041d khi mở GUI Nexus rồi switch sang Ample: over-gate JUCE message window (g_juceOwnerTids, chỉ chạy khi close_in_flight) + gỡ VEH tạm và mọi log [dbg] chẩn đoán, giữ [NativeBridge] production; deploy exe FINAL (đã verify 3 run driver)
This commit is contained in:
@@ -213,14 +213,12 @@ bool Vst3Instrument::loadPlugin(const std::string& path, double sampleRate) {
|
||||
using namespace VST3::Hosting;
|
||||
|
||||
std::string err;
|
||||
std::cerr << "[dbg] loadPlugin: Module::create ..." << std::endl;
|
||||
Module::Ptr module = Module::create(path, err);
|
||||
if (!module) {
|
||||
std::cerr << "[Vst3Instrument] Module::create failed: " << err << std::endl;
|
||||
return false;
|
||||
}
|
||||
const PluginFactory& factory = module->getFactory();
|
||||
std::cerr << "[dbg] loadPlugin: Module::create OK" << std::endl;
|
||||
|
||||
// Pick the first Audio Module class; prefer an Instrument subcategory.
|
||||
// classInfos() returns a TEMPORARY vector (by value) — never keep a
|
||||
@@ -244,16 +242,12 @@ bool Vst3Instrument::loadPlugin(const std::string& path, double sampleRate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cerr << "[dbg] loadPlugin: createInstance ..." << std::endl;
|
||||
std::cerr << "[dbg] loadPlugin: chosen name=" << chosen.name() << " category=" << chosen.category()
|
||||
<< " subcat=" << chosen.subCategoriesString() << std::endl;
|
||||
IPtr<IComponent> component = factory.createInstance<IComponent>(chosen.ID());
|
||||
if (!component) {
|
||||
std::cerr << "[Vst3Instrument] createInstance<IComponent> failed" << std::endl;
|
||||
return false;
|
||||
}
|
||||
IPtr<HostApplication> hostApp = owned(new HostApplication());
|
||||
std::cerr << "[dbg] loadPlugin: initialize ..." << std::endl;
|
||||
FUnknownPtr<IPluginBase> plugBase(component.get());
|
||||
if (!plugBase || plugBase->initialize(hostApp) != kResultOk) {
|
||||
std::cerr << "[Vst3Instrument] component initialize failed" << std::endl;
|
||||
@@ -269,13 +263,8 @@ bool Vst3Instrument::loadPlugin(const std::string& path, double sampleRate) {
|
||||
} else {
|
||||
Steinberg::TUID cid = {};
|
||||
tresult cidRes = component->getControllerClassId(cid);
|
||||
std::cerr << "[dbg] loadPlugin: getControllerClassId=" << (int)cidRes
|
||||
<< " cid=";
|
||||
for (int b = 0; b < 16; ++b) std::cerr << std::hex << (int)(unsigned char)cid[b] << ' ';
|
||||
std::cerr << std::dec << std::endl;
|
||||
if (cidRes == kResultTrue || cidRes == kResultOk) {
|
||||
controller = factory.createInstance<IEditController>(VST3::UID(cid));
|
||||
std::cerr << "[dbg] loadPlugin: controller from factory=" << (controller ? 1 : 0) << std::endl;
|
||||
if (controller) {
|
||||
FUnknownPtr<IPluginBase> ctrlBase(controller.get());
|
||||
if (!ctrlBase || ctrlBase->initialize(hostApp) != kResultOk) controller = nullptr;
|
||||
@@ -326,13 +315,11 @@ bool Vst3Instrument::loadPlugin(const std::string& path, double sampleRate) {
|
||||
std::cerr << "[Vst3Instrument] no IAudioProcessor" << std::endl;
|
||||
return false;
|
||||
}
|
||||
std::cerr << "[dbg] loadPlugin: setupProcessing ..." << std::endl;
|
||||
ProcessSetup setup{kRealtime, kSample32, (int32)maxBlockSize_, sampleRate};
|
||||
if (processor->setupProcessing(setup) != kResultOk) {
|
||||
std::cerr << "[Vst3Instrument] setupProcessing failed" << std::endl;
|
||||
return false;
|
||||
}
|
||||
std::cerr << "[dbg] loadPlugin: setActive ..." << std::endl;
|
||||
if (component->setActive(true) != kResultOk) {
|
||||
std::cerr << "[Vst3Instrument] setActive failed" << std::endl;
|
||||
return false;
|
||||
@@ -342,7 +329,6 @@ bool Vst3Instrument::loadPlugin(const std::string& path, double sampleRate) {
|
||||
// Build per-bus buffers sized maxBlockSize_ (HostProcessData owns them;
|
||||
// we must NOT override channelBuffers with external pointers — unprepare
|
||||
// would delete[] them).
|
||||
std::cerr << "[dbg] loadPlugin: processData.prepare ..." << std::endl;
|
||||
if (!s->processData.prepare(*component, (int32)maxBlockSize_, kSample32)) {
|
||||
std::cerr << "[Vst3Instrument] processData.prepare failed" << std::endl;
|
||||
return false;
|
||||
@@ -356,7 +342,6 @@ bool Vst3Instrument::loadPlugin(const std::string& path, double sampleRate) {
|
||||
outChannels = bi.channelCount;
|
||||
}
|
||||
|
||||
std::cerr << "[dbg] loadPlugin: prepare OK, wiring state" << std::endl;
|
||||
// SDK EventList default maxSize=50 is far too small for the STOP
|
||||
// all-notes-off sweep (128 note-offs per channel). addEvent beyond the
|
||||
// cap fails SILENTLY → notes never released → stuck sound loop.
|
||||
@@ -554,7 +539,6 @@ bool Vst3Instrument::reloadForGUI() {
|
||||
// PHAN NAY PHAI chay tren worker thread — apartment cua channel song
|
||||
// o day; chay tren thread tam thi apartment moi chet ngay sau do
|
||||
// (reopen lan sau -> treo nhu bridge_like).
|
||||
std::cerr << "[dbg] openGUI: re-attach - reloading fresh plugin instance" << std::endl;
|
||||
if (!reload()) return false;
|
||||
s = static_cast<Vst3HostState*>(state_);
|
||||
if (!s || !s->controller) return false;
|
||||
@@ -569,35 +553,21 @@ bool Vst3Instrument::attachView(void* parentWindowHandle) {
|
||||
return false;
|
||||
#else
|
||||
auto* s = static_cast<Vst3HostState*>(state_);
|
||||
std::cerr << "[dbg] openGUI hwnd=" << (void*)(uintptr_t)parentWindowHandle
|
||||
<< " controller=" << (s ? (s->controller ? 1 : 0) : -1) << std::endl;
|
||||
if (!s || !s->controller || !parentWindowHandle) return false;
|
||||
IPlugView* rawView = nullptr;
|
||||
tresult qi = s->controller->queryInterface(IPlugView::iid, (void**)&rawView);
|
||||
std::cerr << "[dbg] openGUI: controller qi IPlugView=" << (int)qi << " raw=" << (void*)rawView << " isSingle=" << (s->controllerIsComponent ? 1 : 0) << std::endl;
|
||||
FUnknownPtr<IPlugView> view(rawView);
|
||||
if (!view) {
|
||||
// Mot so plugin khong expose IPlugView tren edit controller; thu component.
|
||||
std::cerr << "[dbg] openGUI: controller no IPlugView, trying component" << std::endl;
|
||||
IPlugView* rawViewC = nullptr;
|
||||
tresult qic = s->component->queryInterface(IPlugView::iid, (void**)&rawViewC);
|
||||
std::cerr << "[dbg] openGUI: component qi IPlugView=" << (int)qic << " raw=" << (void*)rawViewC << std::endl;
|
||||
view = FUnknownPtr<IPlugView>(rawViewC);
|
||||
}
|
||||
if (!view) {
|
||||
// Official editorhost.cpp pattern: IEditController::createView(kEditor).
|
||||
// JUCE-based plugins (Scaler2) expose the editor only this way.
|
||||
std::cerr << "[dbg] openGUI: qi failed, trying controller->createView(kEditor)" << std::endl;
|
||||
view = owned(s->controller->createView(Steinberg::Vst::ViewType::kEditor));
|
||||
std::cerr << "[dbg] openGUI: createView view=" << (view ? "ok" : "null") << std::endl;
|
||||
}
|
||||
if (!view) { std::cerr << "[dbg] openGUI: no IPlugView" << std::endl; return false; }
|
||||
view->setFrame(&s->plugFrame);
|
||||
tresult ts = view->isPlatformTypeSupported(kPlatformTypeHWND);
|
||||
std::cerr << "[dbg] openGUI: isPlatformTypeSupported=" << (int)ts << std::endl;
|
||||
// Log only — proceed to attach anyway to support non-compliant plugins.
|
||||
tresult ta = view->attached(parentWindowHandle, kPlatformTypeHWND);
|
||||
std::cerr << "[dbg] openGUI: attached=" << (int)ta << std::endl;
|
||||
if (ta != kResultOk) return false;
|
||||
#ifdef _WIN32
|
||||
HWND hwnd = (HWND)parentWindowHandle;
|
||||
@@ -663,9 +633,6 @@ void Vst3Instrument::closeGUI() {
|
||||
// path out. Callers (post_close_gui / load job) additionally destroy the
|
||||
// editor's child windows right here on this thread so the plugin stops
|
||||
// pumping; the leaked editor object is inert once its windows are gone.
|
||||
if (s && s->view && guiAttached_)
|
||||
std::cerr << "[dbg] closeGUI: skip view->removed() (Nexus deadlock) view="
|
||||
<< (void*)s->view << std::endl;
|
||||
if (s) s->view = nullptr;
|
||||
guiAttached_ = false;
|
||||
#endif
|
||||
@@ -696,8 +663,6 @@ void Vst3Instrument::processAudioBlock(float* outputL, float* outputR, uint32_t
|
||||
(double)s->processContext.projectTimeSamples / s->processContext.sampleRate *
|
||||
(s->processContext.tempo / 60.0);
|
||||
|
||||
static uint32_t dbgN = 0;
|
||||
static int dbgMaxShown = 0; // ev>0 blocks printed (raised: sweep must be visible)
|
||||
// VST3: host buffers must be zeroed (silence) before process — plugins
|
||||
// that skip output leave garbage otherwise (EZkeys 2 -> huge noise).
|
||||
if (s->processData.numOutputs > 0) {
|
||||
@@ -727,19 +692,6 @@ void Vst3Instrument::processAudioBlock(float* outputL, float* outputR, uint32_t
|
||||
std::memset(outputL, 0, numSamples * sizeof(float));
|
||||
std::memset(outputR, 0, numSamples * sizeof(float));
|
||||
}
|
||||
uint32_t evc = s->eventList.getEventCount();
|
||||
int evt = -1;
|
||||
if (evc > 0) {
|
||||
const Event* e0 = s->eventList.getEventByIndex(0);
|
||||
evt = e0 ? (int)e0->type : -2;
|
||||
}
|
||||
if ((++dbgN % 250) == 0 || (evc > 0 && dbgMaxShown < 5000)) {
|
||||
if (evc > 0) ++dbgMaxShown;
|
||||
std::cerr << "[dbg] pid=" << (int)GetCurrentProcessId() << " ch=" << channel_ << " n=" << numSamples << " ev=" << evc << " evt=" << evt
|
||||
<< " pr=" << (int)pr << " nOut=" << s->processData.numOutputs
|
||||
<< " mx=" << mx << " ts=" << s->processContext.projectTimeSamples
|
||||
<< " nch=" << (s->processData.numOutputs > 0 ? s->processData.outputs[0].numChannels : -1) << std::endl;
|
||||
}
|
||||
s->eventList.clear();
|
||||
s->paramChanges.clearQueue();
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user