mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-09 20:29:10 +02:00
[yabridgectl] Set up in ~/.vst/yabridge by default
Instead of creating `.so` files next to the VST2 plugin's `.dll` files. This behavior is still available as an option. #123
This commit is contained in:
+31
-6
@@ -8,6 +8,13 @@ Versioning](https://semver.org/spec/v2.0.0.html).
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### TODOs
|
||||||
|
|
||||||
|
- The readme documentation has not yet been updated to reflect the changes on
|
||||||
|
the master branch. The main thing that would require documentation changes is
|
||||||
|
the default VST2 plugin handling. Those are now set up in `~/.vst/yabridge` by
|
||||||
|
default, with an option to revert back to the old inline behavior.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Yabridge 4.0 introduces a completely new way to load plugins that allows
|
- Yabridge 4.0 introduces a completely new way to load plugins that allows
|
||||||
@@ -57,8 +64,8 @@ Versioning](https://semver.org/spec/v2.0.0.html).
|
|||||||
|
|
||||||
- Removed the `with-static-boost` build option since there's no longer a
|
- Removed the `with-static-boost` build option since there's no longer a
|
||||||
dependency on Boost.Filesystem.
|
dependency on Boost.Filesystem.
|
||||||
- Removed the `yabridge-group*` binaries as they are now part of the
|
- Removed the `yabridge-group` binaries as they are now part of the
|
||||||
`yabridge-host*` binaries. This saves precious megabytes.
|
`yabridge-host` binaries. This saves precious megabytes.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
@@ -69,11 +76,27 @@ Versioning](https://semver.org/spec/v2.0.0.html).
|
|||||||
|
|
||||||
### yabridgectl
|
### yabridgectl
|
||||||
|
|
||||||
|
- VST2 plugins are now set up in `~/.vst/yabridge` by default. This means that
|
||||||
|
you no longer have to add any directory search locations in your DAW. The
|
||||||
|
downside is that it's no longer possible for two plugin directories (perhaps
|
||||||
|
in different Wine prefixes) to provide the same plugin file. Like with
|
||||||
|
yabridgectl's VST3 handling, the subdirectory structure within the plugin
|
||||||
|
directory is preserved. You can use `yabridgectl set --vst2-location=inline`
|
||||||
|
to revert back to the old behavior of setting the plugins up right next to the
|
||||||
|
VST2 plugin `.dll` files.
|
||||||
|
|
||||||
|
If you were using a `yabridge.toml` configuration file, then you will now need
|
||||||
|
to place that file in `~/.vst/yabridge` instead.
|
||||||
|
|
||||||
- As mentioned above, yabridgectl will now use the new chainloading libraries
|
- As mentioned above, yabridgectl will now use the new chainloading libraries
|
||||||
when setting up plugins. This means that once you've ran `yabridgectl sync`
|
when setting up plugins. This means that once you've ran `yabridgectl sync`
|
||||||
once after updating to yabridge 4.0, yabridge can now be updated without
|
once after updating to yabridge 4.0, yabridge can now be updated without
|
||||||
needing to rerun `yabridgectl sync`. This is particularly useful when using a
|
needing to rerun `yabridgectl sync`. This is particularly useful when using a
|
||||||
distro packaged version of yabridge.
|
distro packaged version of yabridge.
|
||||||
|
|
||||||
|
- The VST3 subdirectory detection is more robust and can now handle arbitrary
|
||||||
|
directories, not just directories that are called `VST3`. This, of course,
|
||||||
|
should not be needed.
|
||||||
- The previously deprecated symlink installation method has now been removed
|
- The previously deprecated symlink installation method has now been removed
|
||||||
from yabridgectl, along with the `yabridgectl set --method` option.
|
from yabridgectl, along with the `yabridgectl set --method` option.
|
||||||
- `yabridgectl status` now lists the architecture of
|
- `yabridgectl status` now lists the architecture of
|
||||||
@@ -87,12 +110,14 @@ Versioning](https://semver.org/spec/v2.0.0.html).
|
|||||||
- The `yabridge-group` binaries no longer exist as they are now part of the
|
- The `yabridge-group` binaries no longer exist as they are now part of the
|
||||||
`yabridge-host` binaries.
|
`yabridge-host` binaries.
|
||||||
- The `with-bitbridge` build option has been renamed to just `bitbridge`.
|
- The `with-bitbridge` build option has been renamed to just `bitbridge`.
|
||||||
- Completely removed the dependency on all Boost libraries.
|
- Both runtime and compile time dependencies on the Boost libraries have been
|
||||||
- Added a dependency on the headers-only
|
removed.
|
||||||
|
- There's a new dependency on the headers-only
|
||||||
[`ghc::filesystem`](https://github.com/gulrak/filesystem) library to replace
|
[`ghc::filesystem`](https://github.com/gulrak/filesystem) library to replace
|
||||||
Boost.Filesystem.
|
Boost.Filesystem. A Meson wrap is included as a fallback for a distro package.
|
||||||
- Added a dependency on the headers-only [Asio](http://think-async.com/Asio/)
|
- Added a dependency on the headers-only [Asio](http://think-async.com/Asio/)
|
||||||
library to replace Boost.Asio.
|
library to replace Boost.Asio. A Meson wrap is included as a fallback for a
|
||||||
|
distro package.
|
||||||
- Fixed a deprecation warning in the Meson build, causing the minimum supported
|
- Fixed a deprecation warning in the Meson build, causing the minimum supported
|
||||||
Meson version to be bumped up to **Meson 0.56** from 0.55.
|
Meson version to be bumped up to **Meson 0.56** from 0.55.
|
||||||
|
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ class HostProcess {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the full path to the host application in use. The host application
|
* Return the full path to the host application in use. The host application
|
||||||
* is chosen depending on the architecture of the plugin's DLL file and on
|
* is chosen depending on the architecture of the plugin's `.dll` file and
|
||||||
* the hosting mode.
|
* on the hosting mode.
|
||||||
*/
|
*/
|
||||||
virtual ghc::filesystem::path path() = 0;
|
virtual ghc::filesystem::path path() = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ use std::fs;
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
use crate::config::{yabridge_vst3_home, Config, Vst2InstallationLocation, YabridgeFiles};
|
use crate::config::{
|
||||||
|
yabridge_vst2_home, yabridge_vst3_home, Config, Vst2InstallationLocation, YabridgeFiles,
|
||||||
|
};
|
||||||
use crate::files::{self, NativeFile, Plugin, Vst2Plugin};
|
use crate::files::{self, NativeFile, Plugin, Vst2Plugin};
|
||||||
use crate::utils::{self, get_file_type};
|
use crate::utils::{self, get_file_type};
|
||||||
use crate::utils::{verify_path_setup, verify_wine_setup};
|
use crate::utils::{verify_path_setup, verify_wine_setup};
|
||||||
@@ -145,7 +147,7 @@ pub fn show_status(config: &Config) -> Result<()> {
|
|||||||
println!("\n{}", path.join("").display());
|
println!("\n{}", path.join("").display());
|
||||||
|
|
||||||
for (plugin_path, (plugin, status)) in
|
for (plugin_path, (plugin, status)) in
|
||||||
search_results.installation_status(files.as_ref().ok())
|
search_results.installation_status(config, files.as_ref().ok())
|
||||||
{
|
{
|
||||||
let plugin_type = match plugin {
|
let plugin_type = match plugin {
|
||||||
Plugin::Vst2(Vst2Plugin { architecture, .. }) => {
|
Plugin::Vst2(Vst2Plugin { architecture, .. }) => {
|
||||||
@@ -263,14 +265,23 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> {
|
|||||||
// `.so` files and unused VST3 modules we found during scanning that didn't have a corresponding
|
// `.so` files and unused VST3 modules we found during scanning that didn't have a corresponding
|
||||||
// copy or symlink of `libyabridge-chainloader-vst2.so`
|
// copy or symlink of `libyabridge-chainloader-vst2.so`
|
||||||
let mut orphan_files: Vec<NativeFile> = Vec::new();
|
let mut orphan_files: Vec<NativeFile> = Vec::new();
|
||||||
|
// When using the centralized VST2 installation location in `~/.vst/yabridge` we'll want to
|
||||||
|
// track all unmanaged files in that directory and add them to the orphans list
|
||||||
|
let mut known_centralized_vst2_files: HashSet<PathBuf> = HashSet::new();
|
||||||
// Since VST3 bundles contain multiple files from multiple sources (native library files from
|
// Since VST3 bundles contain multiple files from multiple sources (native library files from
|
||||||
// yabridge, and symlinks to Windows VST3 modules or bundles), cleaning up orphan VST3 files is
|
// yabridge, and symlinks to Windows VST3 modules or bundles), cleaning up orphan VST3 files is
|
||||||
// a bit more complicated. We want to clean both `.vst3` bundles that weren't used by anything
|
// a bit more complicated. We want to clean both `.vst3` bundles that weren't used by anything
|
||||||
// during the syncing process, so we'll keep track of which VST3 files we touched per-bundle. We
|
// during the syncing process, so we'll keep track of which VST3 files we touched per-bundle. We
|
||||||
// can then at the end remove all unkonwn bundles, and all unkonwn files within a bundle.
|
// can then at the end remove all unkonwn bundles, and all unkonwn files within a bundle.
|
||||||
let mut known_vst3_files: HashMap<PathBuf, HashSet<PathBuf>> = HashMap::new();
|
let mut known_centralized_vst3_files: HashMap<PathBuf, HashSet<PathBuf>> = HashMap::new();
|
||||||
for (path, search_results) in results {
|
for (path, search_results) in results {
|
||||||
orphan_files.extend(search_results.vst2_orphans().into_iter().cloned());
|
// Orphan files in the centralized directories need to be detected separately
|
||||||
|
orphan_files.extend(
|
||||||
|
search_results
|
||||||
|
.vst2_inline_orphans(config)
|
||||||
|
.into_iter()
|
||||||
|
.cloned(),
|
||||||
|
);
|
||||||
skipped_dll_files.extend(search_results.skipped_files);
|
skipped_dll_files.extend(search_results.skipped_files);
|
||||||
|
|
||||||
if options.verbose {
|
if options.verbose {
|
||||||
@@ -282,27 +293,78 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> {
|
|||||||
for plugin in search_results.plugins {
|
for plugin in search_results.plugins {
|
||||||
// If verbose mode is enabled we'll print the path to the plugin after setting it up
|
// If verbose mode is enabled we'll print the path to the plugin after setting it up
|
||||||
let plugin_path: PathBuf = match plugin {
|
let plugin_path: PathBuf = match plugin {
|
||||||
// We'll set up the copies or symlinks for VST2 plugins
|
// VST2 plugins can be set up in either `~/.vst/yabridge` or inline with the
|
||||||
Plugin::Vst2(Vst2Plugin {
|
// plugin's `.dll` file
|
||||||
path: plugin_path, ..
|
Plugin::Vst2(vst2_plugin) => {
|
||||||
}) => {
|
match config.vst2_location {
|
||||||
let target_path = plugin_path.with_extension("so");
|
Vst2InstallationLocation::Centralized => {
|
||||||
let normalized_target_path = utils::normalize_path(&target_path);
|
let target_native_plugin_path = vst2_plugin.centralized_native_target();
|
||||||
|
let target_windows_plugin_path =
|
||||||
|
vst2_plugin.centralized_windows_target();
|
||||||
|
let normalized_target_native_plugin_path =
|
||||||
|
utils::normalize_path(&target_native_plugin_path);
|
||||||
|
|
||||||
// Since we skip some files, we'll also keep track of how many new file we've
|
let mut is_new = known_centralized_vst2_files
|
||||||
// actually set up
|
.insert(target_native_plugin_path.clone());
|
||||||
if install_file(
|
is_new |= known_centralized_vst2_files
|
||||||
options.force,
|
.insert(target_windows_plugin_path.clone());
|
||||||
InstallationMethod::Copy,
|
if !is_new {
|
||||||
&files.vst2_chainloader,
|
eprintln!(
|
||||||
Some(vst2_chainloader_hash),
|
"{}",
|
||||||
&target_path,
|
utils::wrap(&format!(
|
||||||
)? {
|
"{}: '{}' has already been provided by another Wine prefix or plugin directory, skipping it\n",
|
||||||
new_plugins.insert(normalized_target_path.clone());
|
"WARNING".red(),
|
||||||
|
target_windows_plugin_path.display(),
|
||||||
|
))
|
||||||
|
);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the centralized mode we'll create a copy of
|
||||||
|
// `libyabridge-chainloader-vst2.so` to (a subdirectory of)
|
||||||
|
// `~/.vst/yabridge`, and then we'll symlink the Windows VST2 plugin
|
||||||
|
// `.dll` file right next to it
|
||||||
|
utils::create_dir_all(target_native_plugin_path.parent().unwrap())?;
|
||||||
|
if install_file(
|
||||||
|
options.force,
|
||||||
|
InstallationMethod::Copy,
|
||||||
|
&files.vst2_chainloader,
|
||||||
|
Some(vst2_chainloader_hash),
|
||||||
|
&target_native_plugin_path,
|
||||||
|
)? {
|
||||||
|
new_plugins.insert(normalized_target_native_plugin_path.clone());
|
||||||
|
}
|
||||||
|
managed_plugins.insert(normalized_target_native_plugin_path);
|
||||||
|
|
||||||
|
install_file(
|
||||||
|
true,
|
||||||
|
InstallationMethod::Symlink,
|
||||||
|
&vst2_plugin.path,
|
||||||
|
None,
|
||||||
|
&target_windows_plugin_path,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
Vst2InstallationLocation::Inline => {
|
||||||
|
let target_path = vst2_plugin.inline_native_target();
|
||||||
|
let normalized_target_path = utils::normalize_path(&target_path);
|
||||||
|
|
||||||
|
// Since we skip some files, we'll also keep track of how many new file we've
|
||||||
|
// actually set up
|
||||||
|
if install_file(
|
||||||
|
options.force,
|
||||||
|
InstallationMethod::Copy,
|
||||||
|
&files.vst2_chainloader,
|
||||||
|
Some(vst2_chainloader_hash),
|
||||||
|
&target_path,
|
||||||
|
)? {
|
||||||
|
new_plugins.insert(normalized_target_path.clone());
|
||||||
|
}
|
||||||
|
managed_plugins.insert(normalized_target_path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
managed_plugins.insert(normalized_target_path);
|
|
||||||
|
|
||||||
plugin_path.clone()
|
vst2_plugin.path.clone()
|
||||||
}
|
}
|
||||||
// And then create merged bundles for the VST3 plugins:
|
// And then create merged bundles for the VST3 plugins:
|
||||||
// https://developer.steinberg.help/display/VST/Plug-in+Format+Structure#PluginFormatStructure-MergedBundle
|
// https://developer.steinberg.help/display/VST/Plug-in+Format+Structure#PluginFormatStructure-MergedBundle
|
||||||
@@ -321,7 +383,7 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> {
|
|||||||
// 32-bit and 64-bit versions of the plugin can live inside of the same bundle),
|
// 32-bit and 64-bit versions of the plugin can live inside of the same bundle),
|
||||||
// but it's not possible to use the exact same plugin from multiple Wine
|
// but it's not possible to use the exact same plugin from multiple Wine
|
||||||
// prefixes at the same time so we'll warn when that happens
|
// prefixes at the same time so we'll warn when that happens
|
||||||
let managed_vst3_bundle_files = known_vst3_files
|
let managed_vst3_bundle_files = known_centralized_vst3_files
|
||||||
.entry(target_bundle_home.clone())
|
.entry(target_bundle_home.clone())
|
||||||
.or_insert_with(HashSet::new);
|
.or_insert_with(HashSet::new);
|
||||||
if managed_vst3_bundle_files.contains(&target_windows_module_path) {
|
if managed_vst3_bundle_files.contains(&target_windows_module_path) {
|
||||||
@@ -329,7 +391,7 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> {
|
|||||||
"{}",
|
"{}",
|
||||||
utils::wrap(&format!(
|
utils::wrap(&format!(
|
||||||
"{}: The {} version of '{}' has already been provided by another Wine \
|
"{}: The {} version of '{}' has already been provided by another Wine \
|
||||||
prefix, skipping '{}'\n",
|
prefix or plugin directory, skipping '{}'\n",
|
||||||
"WARNING".red(),
|
"WARNING".red(),
|
||||||
module.architecture,
|
module.architecture,
|
||||||
module.target_bundle_home().display(),
|
module.target_bundle_home().display(),
|
||||||
@@ -420,10 +482,30 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> {
|
|||||||
println!();
|
println!();
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want to remove both unmanaged VST3 bundles in `~/.vst3/yabridge` as well as
|
// We've already kept track of orphan `.dll` files in the plugin directories, but now we need to
|
||||||
// unmanged files within managed bundles. That's why we'll immediately filter out
|
// do something similar for orphan files in `~/.vst/yabridge` and `~/.vst3/yabridge`. For VST3
|
||||||
// kown files within VST3 bundles.
|
// plugins we'll want to remove both unmanaged VST3 bundles in `~/.vst3/yabridge` as well as
|
||||||
|
// unmanged files within managed bundles. That's why we'll immediately filter out known files
|
||||||
|
// within VST3 bundles. For VST2 plugins we can simply treat any file in `~/.vst/yabridge` that
|
||||||
|
// we did not add to `known_centralized_vst2_files` as an orphan. We'll want to do this
|
||||||
|
// regardless of the VST2 installation location setting so switching between the two modes and
|
||||||
|
// then pruning works as expected.
|
||||||
// TODO: Move this elsewhere
|
// TODO: Move this elsewhere
|
||||||
|
let centralized_vst2_files = WalkDir::new(yabridge_vst2_home())
|
||||||
|
.follow_links(true)
|
||||||
|
.same_file_system(true)
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|e| e.ok())
|
||||||
|
.filter(|entry| !entry.file_type().is_dir())
|
||||||
|
.filter(|entry| {
|
||||||
|
matches!(
|
||||||
|
entry
|
||||||
|
.path()
|
||||||
|
.extension()
|
||||||
|
.and_then(|extension| extension.to_str()),
|
||||||
|
Some("dll" | "so")
|
||||||
|
)
|
||||||
|
});
|
||||||
let installed_vst3_bundles = WalkDir::new(yabridge_vst3_home())
|
let installed_vst3_bundles = WalkDir::new(yabridge_vst3_home())
|
||||||
.follow_links(true)
|
.follow_links(true)
|
||||||
.same_file_system(true)
|
.same_file_system(true)
|
||||||
@@ -437,8 +519,16 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> {
|
|||||||
.and_then(|extension| extension.to_str())
|
.and_then(|extension| extension.to_str())
|
||||||
== Some("vst3")
|
== Some("vst3")
|
||||||
});
|
});
|
||||||
|
|
||||||
|
orphan_files.extend(centralized_vst2_files.filter_map(|entry| {
|
||||||
|
if known_centralized_vst2_files.contains(entry.path()) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
get_file_type(entry.path().to_owned())
|
||||||
|
}
|
||||||
|
}));
|
||||||
for bundle in installed_vst3_bundles {
|
for bundle in installed_vst3_bundles {
|
||||||
match known_vst3_files.get(bundle.path()) {
|
match known_centralized_vst3_files.get(bundle.path()) {
|
||||||
None => orphan_files.push(NativeFile::Directory(bundle.path().to_owned())),
|
None => orphan_files.push(NativeFile::Directory(bundle.path().to_owned())),
|
||||||
Some(managed_vst3_bundle_files) => {
|
Some(managed_vst3_bundle_files) => {
|
||||||
// Find orphan files and symlinks within this bundle. We need this to be able to
|
// Find orphan files and symlinks within this bundle. We need this to be able to
|
||||||
@@ -480,7 +570,10 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for file in orphan_files {
|
// NOTE: This is done in reverse lexicographical order to make sure subdirectories are
|
||||||
|
// cleaned before their parent directories
|
||||||
|
orphan_files.sort_by(|a, b| b.path().cmp(a.path()));
|
||||||
|
for file in orphan_files.into_iter() {
|
||||||
println!("- {}", file.path().display());
|
println!("- {}", file.path().display());
|
||||||
if options.prune {
|
if options.prune {
|
||||||
match &file {
|
match &file {
|
||||||
|
|||||||
@@ -49,6 +49,10 @@ pub const YABRIDGE_HOST_32_EXE_NAME: &str = "yabridge-host-32.exe";
|
|||||||
/// `$XDG_CONFIG_HOME` and `$XDG_DATA_HOME`.
|
/// `$XDG_CONFIG_HOME` and `$XDG_DATA_HOME`.
|
||||||
const YABRIDGE_PREFIX: &str = "yabridge";
|
const YABRIDGE_PREFIX: &str = "yabridge";
|
||||||
|
|
||||||
|
/// The path relative to `$HOME` we will set up bridged VST2 plugins in when using the centralized
|
||||||
|
/// VST2 installation location setting. By putting this in a subdirectory we can easily clean up any
|
||||||
|
/// orphan files without interfering with other native plugins.
|
||||||
|
const YABRIDGE_VST2_HOME: &str = ".vst/yabridge";
|
||||||
/// The path relative to `$HOME` that VST3 modules bridged by yabridgectl life in. By putting this
|
/// The path relative to `$HOME` that VST3 modules bridged by yabridgectl life in. By putting this
|
||||||
/// in a subdirectory we can easily clean up any orphan files without interfering with other native
|
/// in a subdirectory we can easily clean up any orphan files without interfering with other native
|
||||||
/// plugins.
|
/// plugins.
|
||||||
@@ -322,6 +326,13 @@ pub fn yabridgectl_directories() -> Result<BaseDirectories> {
|
|||||||
BaseDirectories::with_prefix(YABRIDGECTL_PREFIX).context("Error while parsing base directories")
|
BaseDirectories::with_prefix(YABRIDGECTL_PREFIX).context("Error while parsing base directories")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the path where bridged VST2 plugin files should be placed when using the centralized
|
||||||
|
/// installation location setting. This is a subdirectory of `~/.vst` so we can easily clean up
|
||||||
|
/// leftover files without interfering with other native plugins.
|
||||||
|
pub fn yabridge_vst2_home() -> PathBuf {
|
||||||
|
Path::new(&env::var("HOME").expect("$HOME is not set")).join(YABRIDGE_VST2_HOME)
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the path where VST3 modules bridged by yabridgectl should be placed in. This is a
|
/// Get the path where VST3 modules bridged by yabridgectl should be placed in. This is a
|
||||||
/// subdirectory of `~/.vst3` so we can easily clean up leftover files without interfering with
|
/// subdirectory of `~/.vst3` so we can easily clean up leftover files without interfering with
|
||||||
/// other native plugins.
|
/// other native plugins.
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ use std::path::{Path, PathBuf};
|
|||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
use crate::config::{yabridge_vst3_home, YabridgeFiles};
|
use crate::config::{yabridge_vst2_home, yabridge_vst3_home, Config, YabridgeFiles};
|
||||||
use crate::utils::get_file_type;
|
use crate::utils::get_file_type;
|
||||||
|
|
||||||
/// Stores the results from searching through a directory. We'll search for Windows VST2 plugin
|
/// Stores the results from searching through a directory. We'll search for Windows VST2 plugin
|
||||||
@@ -125,6 +125,47 @@ pub enum Vst3ModuleType {
|
|||||||
Bundle(PathBuf),
|
Bundle(PathBuf),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Vst2Plugin {
|
||||||
|
/// Get the absolute path to the `.so` file we should create in `~/.vst/yabridge` for this
|
||||||
|
/// plugin when using the centralized VST installation location mode.
|
||||||
|
pub fn centralized_native_target(&self) -> PathBuf {
|
||||||
|
let file_name = self
|
||||||
|
.path
|
||||||
|
.file_name()
|
||||||
|
.unwrap()
|
||||||
|
.to_str()
|
||||||
|
.expect("Plugin name contains invalid UTF-8");
|
||||||
|
let file_name = Path::new(file_name).with_extension("so");
|
||||||
|
|
||||||
|
match &self.subdirectory {
|
||||||
|
Some(directory) => yabridge_vst2_home().join(directory).join(file_name),
|
||||||
|
None => yabridge_vst2_home().join(file_name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the absolute path to the `.dll` file we should symlink to `~/.vst/yabridge` when setting
|
||||||
|
/// this plugin up with the centralized VST2 installation location setting.
|
||||||
|
pub fn centralized_windows_target(&self) -> PathBuf {
|
||||||
|
let file_name = self
|
||||||
|
.path
|
||||||
|
.file_name()
|
||||||
|
.unwrap()
|
||||||
|
.to_str()
|
||||||
|
.expect("Plugin name contains invalid UTF-8");
|
||||||
|
|
||||||
|
match &self.subdirectory {
|
||||||
|
Some(directory) => yabridge_vst2_home().join(directory).join(file_name),
|
||||||
|
None => yabridge_vst2_home().join(file_name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the absolute path to the `.so` file we should create when setting this plugin up with
|
||||||
|
/// the inline VST2 installation location setting.
|
||||||
|
pub fn inline_native_target(&self) -> PathBuf {
|
||||||
|
self.path.with_extension("so")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Vst3Module {
|
impl Vst3Module {
|
||||||
/// Get the path to the Windows VST3 plugin. This can be either a file or a directory depending
|
/// Get the path to the Windows VST3 plugin. This can be either a file or a directory depending
|
||||||
/// on the type of moudle.
|
/// on the type of moudle.
|
||||||
@@ -195,7 +236,7 @@ impl Vst3Module {
|
|||||||
/// version of this module. The path here depends on whether we're using a 32-bit or 64-bit
|
/// version of this module. The path here depends on whether we're using a 32-bit or 64-bit
|
||||||
/// version of yabridge. If the configuration is not given (for instance, becuase yabridge is
|
/// version of yabridge. If the configuration is not given (for instance, becuase yabridge is
|
||||||
/// not set up properly) we'll assume the module should be 64-bit.
|
/// not set up properly) we'll assume the module should be 64-bit.
|
||||||
pub fn target_native_module_path(&self, config: Option<&YabridgeFiles>) -> PathBuf {
|
pub fn target_native_module_path(&self, files: Option<&YabridgeFiles>) -> PathBuf {
|
||||||
let native_module_name = match &self.module {
|
let native_module_name = match &self.module {
|
||||||
Vst3ModuleType::Legacy(path) | Vst3ModuleType::Bundle(path) => path
|
Vst3ModuleType::Legacy(path) | Vst3ModuleType::Bundle(path) => path
|
||||||
.with_extension("so")
|
.with_extension("so")
|
||||||
@@ -210,7 +251,7 @@ impl Vst3Module {
|
|||||||
path.push("Contents");
|
path.push("Contents");
|
||||||
|
|
||||||
#[allow(clippy::wildcard_in_or_patterns)]
|
#[allow(clippy::wildcard_in_or_patterns)]
|
||||||
match config.and_then(|c| c.vst3_chainloader.as_ref()) {
|
match files.and_then(|c| c.vst3_chainloader.as_ref()) {
|
||||||
Some((_, LibArchitecture::Lib32)) => path.push("i386-linux"),
|
Some((_, LibArchitecture::Lib32)) => path.push("i386-linux"),
|
||||||
// NOTE: We'll always fall back to this if `libyabridge-chainloader-vst3.so` is not
|
// NOTE: We'll always fall back to this if `libyabridge-chainloader-vst3.so` is not
|
||||||
// found, just so we cannot get any errors during `yabridgectl status` even if
|
// found, just so we cannot get any errors during `yabridgectl status` even if
|
||||||
@@ -280,12 +321,12 @@ impl LibArchitecture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SearchResults {
|
impl SearchResults {
|
||||||
/// Create a map out of all found plugins based on their file path that contains both a
|
/// Create a map out of all found Windows plugins and their current installation status, if the
|
||||||
/// reference to the plugin (so we can print information about it) and the current installation
|
/// plugin has already been set up.
|
||||||
/// status. The installation status will be `None` if the plugin has not yet been set up.
|
|
||||||
pub fn installation_status(
|
pub fn installation_status(
|
||||||
&self,
|
&self,
|
||||||
config: Option<&YabridgeFiles>,
|
config: &Config,
|
||||||
|
files: Option<&YabridgeFiles>,
|
||||||
) -> BTreeMap<PathBuf, (&Plugin, Option<NativeFile>)> {
|
) -> BTreeMap<PathBuf, (&Plugin, Option<NativeFile>)> {
|
||||||
let so_files: HashMap<&Path, &NativeFile> = self
|
let so_files: HashMap<&Path, &NativeFile> = self
|
||||||
.so_files
|
.so_files
|
||||||
@@ -296,12 +337,26 @@ impl SearchResults {
|
|||||||
self.plugins
|
self.plugins
|
||||||
.iter()
|
.iter()
|
||||||
.map(|plugin| match plugin {
|
.map(|plugin| match plugin {
|
||||||
Plugin::Vst2(Vst2Plugin { path, .. }) => {
|
Plugin::Vst2(vst2_plugin) => {
|
||||||
// For VST2 plugins we'll just look at the similarly named `.so` file right next
|
// For VST2 plugins depending on the VST2 installation location setting we'll
|
||||||
// to the plugin `.dll` file.
|
// either look for a matching file in `~/.vst` or we'll just look at the
|
||||||
match so_files.get(path.with_extension("so").as_path()) {
|
// similarly named `.so` file right next to the plugin `.dll` file
|
||||||
Some(&file_type) => (path.clone(), (plugin, Some(file_type.clone()))),
|
match config.vst2_location {
|
||||||
None => (path.clone(), (plugin, None)),
|
crate::config::Vst2InstallationLocation::Centralized => (
|
||||||
|
vst2_plugin.path.clone(),
|
||||||
|
(
|
||||||
|
plugin,
|
||||||
|
get_file_type(vst2_plugin.centralized_native_target()),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
crate::config::Vst2InstallationLocation::Inline => {
|
||||||
|
match so_files.get(vst2_plugin.inline_native_target().as_path()) {
|
||||||
|
Some(&file_type) => {
|
||||||
|
(vst2_plugin.path.clone(), (plugin, Some(file_type.clone())))
|
||||||
|
}
|
||||||
|
None => (vst2_plugin.path.clone(), (plugin, None)),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// We have not stored the paths to the corresponding `.so` files yet for VST3
|
// We have not stored the paths to the corresponding `.so` files yet for VST3
|
||||||
@@ -310,7 +365,7 @@ impl SearchResults {
|
|||||||
vst3_module.original_path().to_owned(),
|
vst3_module.original_path().to_owned(),
|
||||||
(
|
(
|
||||||
plugin,
|
plugin,
|
||||||
get_file_type(vst3_module.target_native_module_path(config)),
|
get_file_type(vst3_module.target_native_module_path(files)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
@@ -318,9 +373,9 @@ impl SearchResults {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Find all `.so` files in the search results that do not belong to a VST2 plugin `.dll` file.
|
/// Find all `.so` files in the search results that do not belong to a VST2 plugin `.dll` file.
|
||||||
/// We cannot yet do the same thing for VST3 plguins because they will all be installed in
|
/// This depends on the VST2 installation location setting. Centralized VST2 and VST3 orphans
|
||||||
/// `~/.vst3`.
|
/// should be detected separately.
|
||||||
pub fn vst2_orphans(&self) -> Vec<&NativeFile> {
|
pub fn vst2_inline_orphans(&self, config: &Config) -> Vec<&NativeFile> {
|
||||||
// We need to store these in a map so we can easily entries with corresponding `.dll` files
|
// We need to store these in a map so we can easily entries with corresponding `.dll` files
|
||||||
let mut orphans: HashMap<&Path, &NativeFile> = self
|
let mut orphans: HashMap<&Path, &NativeFile> = self
|
||||||
.so_files
|
.so_files
|
||||||
@@ -328,9 +383,17 @@ impl SearchResults {
|
|||||||
.map(|file_type| (file_type.path(), file_type))
|
.map(|file_type| (file_type.path(), file_type))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
for plugin in &self.plugins {
|
match config.vst2_location {
|
||||||
if let Plugin::Vst2(Vst2Plugin { path, .. }) = plugin {
|
// When we set up the plugin in `~/.vst`, any `.so` file in a VST2 plugin search
|
||||||
orphans.remove(path.with_extension("so").as_path());
|
// directory should be considered an orphan. This can happen when switching between the
|
||||||
|
// two modes.
|
||||||
|
crate::config::Vst2InstallationLocation::Centralized => (),
|
||||||
|
crate::config::Vst2InstallationLocation::Inline => {
|
||||||
|
for plugin in &self.plugins {
|
||||||
|
if let Plugin::Vst2(Vst2Plugin { path, .. }) = plugin {
|
||||||
|
orphans.remove(path.with_extension("so").as_path());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user