From d39d3a68c133e825e4f99b7eff19e43fe3001f61 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Sun, 10 Dec 2023 22:24:41 +0100 Subject: [PATCH] Add the chainloader side of yabridge_version This can be used by hosts to determine which version of yabridge is in use. --- CHANGELOG.md | 7 ++++++ src/chainloader/clap-chainloader.cpp | 35 ++++++++++++++++++++++++---- src/chainloader/vst2-chainloader.cpp | 35 ++++++++++++++++++++++++---- src/chainloader/vst3-chainloader.cpp | 35 ++++++++++++++++++++++++---- 4 files changed, 97 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 701594f1..0b27348f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,13 @@ Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added + +- The yabridge libraries now export a `yabridge_version` function that hosts can + query to get the yabridge version in use. This will return the yabridge + version that would be loaded when using the plugin, also when called on the + chainloading libraries. + ### Changed - Parsing failures for `yabridge.toml` files will no longer cause plugins to diff --git a/src/chainloader/clap-chainloader.cpp b/src/chainloader/clap-chainloader.cpp index aa86bede..4d6de235 100644 --- a/src/chainloader/clap-chainloader.cpp +++ b/src/chainloader/clap-chainloader.cpp @@ -51,6 +51,11 @@ void (*yabridge_module_free)(ClapPluginBridge* instance) = nullptr; const void* (*yabridge_module_get_factory)(ClapPluginBridge* instance, const char* factory_id) = nullptr; +// This bridges the `yabridge_version()` call from the plugin library. This +// function was added later, so through weird version mixing it may be missing +// on the yabridge library. +char* (*remote_yabridge_version)() = nullptr; + /** * The bridge instance for this chainloader. This is initialized when * `clap_entry.init` first gets called. @@ -89,21 +94,27 @@ bool initialize_library() { return false; } -#define LOAD_FUNCTION(name) \ +#define MAYBE_LOAD_FUNCTION(name) \ do { \ (name) = \ reinterpret_cast(dlsym(library_handle, #name)); \ - if (!(name)) { \ - log_failing_dlsym(yabridge_clap_plugin_name, #name); \ - return false; \ - } \ + } while (false) +#define LOAD_FUNCTION(name) \ + do { \ + MAYBE_LOAD_FUNCTION(name); \ + if (!(name)) { \ + log_failing_dlsym(yabridge_clap_plugin_name, #name); \ + return false; \ + } \ } while (false) LOAD_FUNCTION(yabridge_module_init); LOAD_FUNCTION(yabridge_module_free); LOAD_FUNCTION(yabridge_module_get_factory); + MAYBE_LOAD_FUNCTION(remote_yabridge_version); #undef LOAD_FUNCTION +#undef MAYBE_LOAD_FUNCTION return true; } @@ -163,3 +174,17 @@ CLAP_EXPORT const clap_plugin_entry_t clap_entry = { }; #pragma GCC diagnostic pop + +/** + * This returns the actual yabridge library's version through + * `yabridge_version()`. Reporting the version associated with this chainloader + * wouldn't be very useful, and that would also cause the chainloader to be + * rebuilt on every git commit in development. + */ +extern "C" YABRIDGE_EXPORT char* yabridge_version() { + if (!initialize_library() || !remote_yabridge_version) { + return nullptr; + } + + return remote_yabridge_version(); +} diff --git a/src/chainloader/vst2-chainloader.cpp b/src/chainloader/vst2-chainloader.cpp index a6e9c9a6..444abf57 100644 --- a/src/chainloader/vst2-chainloader.cpp +++ b/src/chainloader/vst2-chainloader.cpp @@ -49,6 +49,11 @@ using AEffect = void; AEffect* (*yabridge_plugin_init)(audioMasterCallback host_callback, const char* plugin_path) = nullptr; +// This bridges the `yabridge_version()` call from the plugin library. This +// function was added later, so through weird version mixing it may be missing +// on the yabridge library. +char* (*remote_yabridge_version)() = nullptr; + /** * The first time one of the exported functions from this library gets called, * we'll need to load the corresponding `libyabridge-*.so` file and fetch the @@ -72,19 +77,25 @@ bool initialize_library() { return false; } -#define LOAD_FUNCTION(name) \ +#define MAYBE_LOAD_FUNCTION(name) \ do { \ (name) = \ reinterpret_cast(dlsym(library_handle, #name)); \ - if (!(name)) { \ - log_failing_dlsym(yabridge_vst2_plugin_name, #name); \ - return false; \ - } \ + } while (false) +#define LOAD_FUNCTION(name) \ + do { \ + MAYBE_LOAD_FUNCTION(name); \ + if (!(name)) { \ + log_failing_dlsym(yabridge_vst2_plugin_name, #name); \ + return false; \ + } \ } while (false) LOAD_FUNCTION(yabridge_plugin_init); + MAYBE_LOAD_FUNCTION(remote_yabridge_version); #undef LOAD_FUNCTION +#undef MAYBE_LOAD_FUNCTION return true; } @@ -109,3 +120,17 @@ extern "C" YABRIDGE_EXPORT AEffect* deprecated_main( YABRIDGE_EXPORT AEffect* deprecated_main(audioMasterCallback audioMaster) { return VSTPluginMain(audioMaster); } + +/** + * This returns the actual yabridge library's version through + * `yabridge_version()`. Reporting the version associated with this chainloader + * wouldn't be very useful, and that would also cause the chainloader to be + * rebuilt on every git commit in development. + */ +extern "C" YABRIDGE_EXPORT char* yabridge_version() { + if (!initialize_library() || !remote_yabridge_version) { + return nullptr; + } + + return remote_yabridge_version(); +} diff --git a/src/chainloader/vst3-chainloader.cpp b/src/chainloader/vst3-chainloader.cpp index ffcf8942..d2621555 100644 --- a/src/chainloader/vst3-chainloader.cpp +++ b/src/chainloader/vst3-chainloader.cpp @@ -51,6 +51,11 @@ void (*yabridge_module_free)(Vst3PluginBridge* instance) = nullptr; PluginFactory* (*yabridge_module_get_plugin_factory)( Vst3PluginBridge* instance) = nullptr; +// This bridges the `yabridge_version()` call from the plugin library. This +// function was added later, so through weird version mixing it may be missing +// on the yabridge library. +char* (*remote_yabridge_version)() = nullptr; + /** * The bridge instance for this chainloader. This is initialized when * `ModuleEntry()` first gets called. @@ -89,21 +94,27 @@ bool initialize_library() { return false; } -#define LOAD_FUNCTION(name) \ +#define MAYBE_LOAD_FUNCTION(name) \ do { \ (name) = \ reinterpret_cast(dlsym(library_handle, #name)); \ - if (!(name)) { \ - log_failing_dlsym(yabridge_vst3_plugin_name, #name); \ - return false; \ - } \ + } while (false) +#define LOAD_FUNCTION(name) \ + do { \ + MAYBE_LOAD_FUNCTION(name); \ + if (!(name)) { \ + log_failing_dlsym(yabridge_vst3_plugin_name, #name); \ + return false; \ + } \ } while (false) LOAD_FUNCTION(yabridge_module_init); LOAD_FUNCTION(yabridge_module_free); LOAD_FUNCTION(yabridge_module_get_plugin_factory); + MAYBE_LOAD_FUNCTION(remote_yabridge_version); #undef LOAD_FUNCTION +#undef MAYBE_LOAD_FUNCTION return true; } @@ -146,3 +157,17 @@ extern "C" YABRIDGE_EXPORT PluginFactory* GetPluginFactory() { return yabridge_module_get_plugin_factory(bridge.get()); } + +/** + * This returns the actual yabridge library's version through + * `yabridge_version()`. Reporting the version associated with this chainloader + * wouldn't be very useful, and that would also cause the chainloader to be + * rebuilt on every git commit in development. + */ +extern "C" YABRIDGE_EXPORT char* yabridge_version() { + if (!initialize_library() || !remote_yabridge_version) { + return nullptr; + } + + return remote_yabridge_version(); +}