diff --git a/src/chainloader/meson.build b/src/chainloader/meson.build
index 195e1367..622904f6 100644
--- a/src/chainloader/meson.build
+++ b/src/chainloader/meson.build
@@ -2,15 +2,19 @@
# main `meson.build` file so everything gets bundled to a single directory.
vst2_chainloader_sources = files(
- 'vst2-chainloader.cpp',
+ '../common/logging/common.cpp',
'../common/linking.cpp',
'../common/notifications.cpp',
'../common/process.cpp',
+ 'utils.cpp',
+ 'vst2-chainloader.cpp',
)
vst3_chainloader_sources = files(
- 'vst3-chainloader.cpp',
+ '../common/logging/common.cpp',
'../common/linking.cpp',
'../common/notifications.cpp',
'../common/process.cpp',
+ 'utils.cpp',
+ 'vst3-chainloader.cpp',
)
diff --git a/src/chainloader/utils.cpp b/src/chainloader/utils.cpp
new file mode 100644
index 00000000..e2cec39b
--- /dev/null
+++ b/src/chainloader/utils.cpp
@@ -0,0 +1,81 @@
+// yabridge: a Wine plugin bridge
+// Copyright (C) 2020-2022 Robbert van der Helm
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+#include "utils.h"
+
+#include
+
+// Generated inside of the build directory
+#include
+
+#include "../common/linking.h"
+#include "../common/logging/common.h"
+#include "../common/notifications.h"
+#include "../common/process.h"
+
+namespace fs = ghc::filesystem;
+
+void* find_plugin_library(const std::string& name) {
+ // Just using a goto for this would probably be cleaner, but yeah...
+ const auto impl = [&name]() -> void* {
+ // If `name` exists right next to the Wine plugin host binary, then
+ // we'll try loading that. Otherwise we'll fall back to regular
+ // `dlopen()` for distro packaged versions of yabridge
+ const std::vector search_path = get_augmented_search_path();
+ if (const auto& yabridge_host_path =
+ search_in_path(search_path, yabridge_individual_host_name)) {
+ const fs::path candidate = yabridge_host_path->parent_path() / name;
+ if (fs::exists(candidate)) {
+ return dlopen(candidate.c_str(), RTLD_LAZY | RTLD_LOCAL);
+ }
+ }
+
+ if (const auto& yabridge_host_32_path = search_in_path(
+ search_path, yabridge_individual_host_name_32bit)) {
+ const fs::path candidate =
+ yabridge_host_32_path->parent_path() / name;
+ if (fs::exists(candidate)) {
+ return dlopen(candidate.c_str(), RTLD_LAZY | RTLD_LOCAL);
+ }
+ }
+
+ return dlopen(name.c_str(), RTLD_LAZY | RTLD_LOCAL);
+ };
+
+ void* handle = impl();
+ if (!handle) {
+ const fs::path this_plugin_path = get_this_file_location();
+
+ Logger logger = Logger::create_exception_logger();
+
+ logger.log("");
+ logger.log("Could not find '" + name + "'.");
+ logger.log("Make sure you followed the installation instructions from");
+ logger.log("yabridge's readme");
+ logger.log("");
+ logger.log("Source: '" + this_plugin_path.string() + "'");
+ logger.log("");
+
+ // Also show a desktop notification since most people likely won't see
+ // the above message
+ send_notification("Could not find '" + name + "'",
+ "Make sure you followed the installation "
+ "instructions from yabridge's readme",
+ this_plugin_path);
+ }
+
+ return handle;
+}
diff --git a/src/chainloader/utils.h b/src/chainloader/utils.h
new file mode 100644
index 00000000..48be7826
--- /dev/null
+++ b/src/chainloader/utils.h
@@ -0,0 +1,37 @@
+// yabridge: a Wine plugin bridge
+// Copyright (C) 2020-2022 Robbert van der Helm
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+#pragma once
+
+#include
+
+/**
+ * Finds the matching `libyabridge-*.so` for this chainloader. Returns the
+ * handle if it is found. Otherwise, we'll log an error and show a desktop
+ * notification, and this function returns a null pointer. The pointer may be
+ * `dlclose()`'d when it's no longer needed. This search works in the following
+ * order:
+ *
+ * - First we'll try to locate `yabridge-host.exe` using the same method used by
+ * the yabridge plugin bridges themselves. We'll search in `$PATH`, followed
+ * by `${XDG_DATA_HOME:-$HOME/.local/share}/yabridge`. If that file exists and
+ * the target plugin library exists right next to it, then we'll use that.
+ * - For compatibility with 32-bit only builds of yabridge, we'll repeat this
+ * process for `yabridge-host-32.exe`.
+ * - When those don't exist, we'll try to `dlopen()` the file directly. This
+ * will use the correct path for the system.
+ */
+void* find_plugin_library(const std::string& name);
diff --git a/src/chainloader/vst2-chainloader.cpp b/src/chainloader/vst2-chainloader.cpp
index a6da808a..030bebaf 100644
--- a/src/chainloader/vst2-chainloader.cpp
+++ b/src/chainloader/vst2-chainloader.cpp
@@ -20,8 +20,12 @@
#include
+// Generated inside of the build directory
+#include
+
#include "../common/linking.h"
#include "../common/utils.h"
+#include "utils.h"
// These chainloader libraries are tiny, mostly dependencyless libraries that
// `dlopen()` the actual `libyabridge-{vst2,vst3}.so` files and forward the
@@ -35,8 +39,6 @@
// distro packaging, because updates to Boost might require the package to be
// rebuilt, which in turn would also require a resync.
-// TODO: Order to check in: See Discord
-
namespace fs = ghc::filesystem;
using audioMasterCallback = void*;
@@ -65,11 +67,10 @@ bool initialize_library() {
return true;
}
- // FIXME: Hardcoded path
- library_handle = dlopen(
- "/home/robbert/Documenten/projecten/yabridge/build/libyabridge-vst2.so",
- RTLD_LAZY | RTLD_LOCAL);
- assert(library_handle);
+ library_handle = find_plugin_library(yabridge_vst2_plugin_name);
+ if (!library_handle) {
+ return false;
+ }
#define LOAD_FUNCTION(name) \
do { \
@@ -89,7 +90,9 @@ extern "C" YABRIDGE_EXPORT AEffect* VSTPluginMain(
audioMasterCallback host_callback) {
assert(host_callback);
- initialize_library();
+ if (!initialize_library()) {
+ return nullptr;
+ }
const fs::path this_plugin_path = get_this_file_location();
return yabridge_plugin_init(host_callback, this_plugin_path.c_str());
diff --git a/src/chainloader/vst3-chainloader.cpp b/src/chainloader/vst3-chainloader.cpp
index 8b476050..3ce91113 100644
--- a/src/chainloader/vst3-chainloader.cpp
+++ b/src/chainloader/vst3-chainloader.cpp
@@ -20,8 +20,12 @@
#include
+// Generated inside of the build directory
+#include
+
#include "../common/linking.h"
#include "../common/utils.h"
+#include "utils.h"
// These chainloader libraries are tiny, mostly dependencyless libraries that
// `dlopen()` the actual `libyabridge-{vst2,vst3}.so` files and forward the
@@ -35,8 +39,6 @@
// distro packaging, because updates to Boost might require the package to be
// rebuilt, which in turn would also require a resync.
-// TODO: Order to check in: See Discord
-
namespace fs = ghc::filesystem;
using Vst3PluginBridge = void;
@@ -83,11 +85,10 @@ bool initialize_library() {
return true;
}
- // FIXME: Hardcoded path
- library_handle = dlopen(
- "/home/robbert/Documenten/projecten/yabridge/build/libyabridge-vst3.so",
- RTLD_LAZY | RTLD_LOCAL);
- assert(library_handle);
+ library_handle = find_plugin_library(yabridge_vst3_plugin_name);
+ if (!library_handle) {
+ return false;
+ }
#define LOAD_FUNCTION(name) \
do { \
@@ -109,7 +110,9 @@ extern "C" YABRIDGE_EXPORT bool ModuleEntry(void*) {
// This function can be called multiple times, so we should make sure to
// only initialize the bridge on the first call
if (active_instances.fetch_add(1, std::memory_order_seq_cst) == 0) {
- assert(initialize_library());
+ if (!initialize_library()) {
+ return false;
+ }
// You can't change the deleter function with `.reset()` so we'll need
// this abomination instead
diff --git a/src/plugin/bridges/common.h b/src/plugin/bridges/common.h
index 61cfc5d2..f42f8860 100644
--- a/src/plugin/bridges/common.h
+++ b/src/plugin/bridges/common.h
@@ -142,6 +142,7 @@ class PluginBridge {
<< " (32-bit build)"
#endif
<< std::endl;
+ // TODO: Show this library's path now that we're chainloading
init_msg << "host: '" << plugin_host_->path().string() << "'"
<< std::endl;
init_msg << "plugin: '" << info_.windows_plugin_path_.string()
diff --git a/src/plugin/vst2-plugin.cpp b/src/plugin/vst2-plugin.cpp
index f5056741..52b7800d 100644
--- a/src/plugin/vst2-plugin.cpp
+++ b/src/plugin/vst2-plugin.cpp
@@ -52,8 +52,8 @@ void log_init_error(const std::exception& error, const fs::path& plugin_path) {
logger.log(error.what());
logger.log("");
- // Also show a desktop notification most people likely won't see the above
- // message
+ // Also show a desktop notification since most people likely won't see the
+ // above message
send_notification(
"Failed to initialize VST2 plugin",
error.what() +
diff --git a/src/plugin/vst3-plugin.cpp b/src/plugin/vst3-plugin.cpp
index 9a430e71..67f73ec4 100644
--- a/src/plugin/vst3-plugin.cpp
+++ b/src/plugin/vst3-plugin.cpp
@@ -77,8 +77,8 @@ void log_init_exception(const std::exception& error,
logger.log(error.what());
logger.log("");
- // Also show a desktop notification most people likely won't see the above
- // message
+ // Also show a desktop notification since most people likely won't see the
+ // above message
// FIXME: Go through these messages and update them to reflect the
// chainloading changes
send_notification(