diff --git a/native_bridge/src/RenderFxJob.cpp b/native_bridge/src/RenderFxJob.cpp index 5b6bef6..e54272e 100644 --- a/native_bridge/src/RenderFxJob.cpp +++ b/native_bridge/src/RenderFxJob.cpp @@ -400,22 +400,33 @@ bool pickFxClass(const VST3::Hosting::PluginFactory& factory, // the DLL search path at the plugin directory before Module::create. #ifdef _WIN32 static void setPluginSearchPath(const std::string& path) { + if (path.empty()) return; std::string dir; - namespace fs = std::filesystem; - try { - fs::path p(path); - // Folder bundle (.vst3 dir): deps live in Contents\\ - if (fs::is_directory(p)) { - dir = (p / "Contents" / "x86_64-win").string(); - if (!fs::is_directory(dir)) dir = (p / "Contents").string(); + // Folder bundle (.vst3 dir): deps live in Contents\\ + // Single file (.vst3/.dll): deps live next to it. + size_t baseSlash = path.find_last_of("/\\"); + std::string base = baseSlash == std::string::npos ? "" : path.substr(baseSlash + 1); + std::string parent = baseSlash == std::string::npos ? "" : path.substr(0, baseSlash); + if (!base.empty() && base.size() > 4 && + base.substr(base.size() - 4) == ".vst3") { + // Could be a folder bundle OR a single .vst3 file. Check folder first. + DWORD attr = GetFileAttributesA(path.c_str()); + if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY)) { + dir = path + "\\Contents\\x86_64-win"; + DWORD dAttr = GetFileAttributesA(dir.c_str()); + if (dAttr == INVALID_FILE_ATTRIBUTES) + dir = path + "\\Contents"; } else { - dir = p.parent_path().string(); // single-file .vst3 / .dll + dir = parent; } - } catch (...) { return; } + } else { + dir = parent; + } if (dir.empty()) return; // SetDllDirectoryW is process-global, fine here: bridge loads one plugin // at a time (render slots serial; realtime chain loads on its own thread). - SetDllDirectoryW(std::wstring(dir.begin(), dir.end()).c_str()); + std::wstring wdir(dir.begin(), dir.end()); + SetDllDirectoryW(wdir.c_str()); std::cerr << "[RenderFx] dll search dir: " << dir << std::endl; } #endif