From 3dc1b1585b473939239a09df590dbfb3aa37feb7 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Wed, 23 Dec 2020 17:41:16 +0100 Subject: [PATCH] [yabridgectl] Add field for indexing VST3 modules --- CHANGELOG.md | 8 +++++ tools/yabridgectl/src/actions.rs | 8 ++--- tools/yabridgectl/src/config.rs | 16 +++++----- tools/yabridgectl/src/files.rs | 52 +++++++++++++++++++++----------- 4 files changed, 55 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3882eb6d..5bd784c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,14 @@ TODO: Add the relevant entries here for yabridge's VST3 support and 5.8 required a change, but that change now breaks builds using Wine 6.0 and up, so this change has been reverted. +### yabridgectl + +- Updated for the changes in yabridge 3.0. Yabridgectl now allows you to set up + yabridge for VST3 plugins. Since `libyabridge.so` got renamed to + `libyabridge-vst2.so` in this version, it's advised to carefully remove the + old `libyabridge.so` and `yabridgectl` files before upgrading to avoid + confusing situations. + ## [2.2.1] - 2020-12-12 ### Fixed diff --git a/tools/yabridgectl/src/actions.rs b/tools/yabridgectl/src/actions.rs index 9a89d736..87127956 100644 --- a/tools/yabridgectl/src/actions.rs +++ b/tools/yabridgectl/src/actions.rs @@ -23,7 +23,7 @@ use std::path::{Path, PathBuf}; use crate::config::{Config, InstallationMethod, YabridgeFiles}; use crate::files; -use crate::files::FoundFile; +use crate::files::NativeSoFile; use crate::utils; use crate::utils::{verify_path_setup, verify_wine_setup}; @@ -121,8 +121,8 @@ pub fn show_status(config: &Config) -> Result<()> { for (plugin, status) in search_results.installation_status() { let status_str = match status { - Some(FoundFile::Regular(_)) => "copy".green(), - Some(FoundFile::Symlink(_)) => "symlink".green(), + Some(NativeSoFile::Regular(_)) => "copy".green(), + Some(NativeSoFile::Symlink(_)) => "symlink".green(), None => "not installed".red(), }; @@ -178,7 +178,7 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> { let mut num_installed = 0; let mut num_new = 0; let mut skipped_dll_files: Vec = Vec::new(); - let mut orphan_so_files: Vec = Vec::new(); + let mut orphan_so_files: Vec = Vec::new(); for (path, search_results) in results { num_installed += search_results.vst2_files.len(); orphan_so_files.extend(search_results.orphans().into_iter().cloned()); diff --git a/tools/yabridgectl/src/config.rs b/tools/yabridgectl/src/config.rs index a0e0c1d7..f891e7c7 100644 --- a/tools/yabridgectl/src/config.rs +++ b/tools/yabridgectl/src/config.rs @@ -55,8 +55,10 @@ pub struct Config { /// yabridgectl will look in `/usr/lib` and `$XDG_DATA_HOME/yabridge` since those are the /// expected locations for yabridge to be installed in. pub yabridge_home: Option, - /// Directories to search for Windows VST plugins. We're using an ordered set here out of - /// convenience so we can't get duplicates and the config file is always sorted. + /// Directories to search for Windows VST plugins. These directories can contain both VST2 + /// plugin `.dll` files and VST3 modules (which should be located in `/drive_c/Program + /// Files/Common/VST3`). We're using an ordered set here out of convenience so we can't get + /// duplicates and the config file is always sorted. pub plugin_dirs: BTreeSet, /// The last known combination of Wine and yabridge versions that would work together properly. /// This is mostly to diagnose issues with older Wine versions (such as those in Ubuntu's repos) @@ -68,11 +70,11 @@ pub struct Config { #[derive(Deserialize, Serialize, Debug, PartialEq, Eq)] #[serde(rename_all = "snake_case")] pub enum InstallationMethod { - /// Create a copy of `libyabridge-{vst2,vst3}.so` for every Windows VST2 plugin .dll file or + /// Create a copy of `libyabridge-{vst2,vst3}.so` for every Windows VST2 plugin `.dll` file or /// VST3 module found. After updating yabridge, the user will have to rerun `yabridgectl sync` /// to copy over the new version. Copy, - /// This will create a symlink to `libyabridge-{vst2,vst3}.so` for every VST2 plugin .dll file + /// This will create a symlink to `libyabridge-{vst2,vst3}.so` for every VST2 plugin `.dll` file /// or VST3 module in the plugin directories. Now that yabridge also searches in /// `~/.local/share/yabridge` since yabridge 2.1 this option is not really needed anymore. Symlink, @@ -251,10 +253,8 @@ impl Config { }) } - /// Search for VST2 plugins in all of the registered plugins directories. This will return an - /// error if `winedump` could not be called. - /// - /// TODO: Next step is including VST3 modules in the search + /// Search for VST2 and VST3 plugins in all of the registered plugins directories. This will + /// return an error if `winedump` could not be called. pub fn index_directories(&self) -> Result> { self.plugin_dirs .par_iter() diff --git a/tools/yabridgectl/src/files.rs b/tools/yabridgectl/src/files.rs index 3544ff34..7209eade 100644 --- a/tools/yabridgectl/src/files.rs +++ b/tools/yabridgectl/src/files.rs @@ -25,35 +25,51 @@ use std::path::{Path, PathBuf}; use std::process::Command; use walkdir::WalkDir; -/// Stores the results from searching for Windows VST plugin `.dll` files and native Linux `.so` -/// files inside of a directory. These `.so` files are kept track of so we can report the current -/// installation status and to be able to prune orphan files. +/// Stores the results from searching through a directory. We'll search for Windows VST2 plugin +/// `.dll` files, Windows VST3 plugin modules, and native Linux `.so` files inside of a directory. +/// These `.so` files are kept track of so we can report the current installation status of VST2 +/// plugins and to be able to prune orphan files. Since VST3 plugins have to be instaleld in +/// `~/.vst3`, these orphan files are only relevant for VST2 plugins. #[derive(Debug)] pub struct SearchResults { /// Absolute paths to the found VST2 `.dll` files. pub vst2_files: Vec, + /// Absolute paths to found VST3 modules. Either legacy `.vst3` DLL files or VST 3.6.10 bundles. + pub vst3_modules: Vec, /// `.dll` files skipped over during the serach. Used for printing statistics and shown when /// running `yabridgectl sync --verbose`. pub skipped_files: Vec, /// Absolute paths to any `.so` files inside of the directory, and whether they're a symlink or /// a regular file. - pub so_files: Vec, + pub so_files: Vec, } +/// Native `.so` files we found during a search. #[derive(Debug, Clone, PartialEq, Eq)] -pub enum FoundFile { +pub enum NativeSoFile { Symlink(PathBuf), Regular(PathBuf), } +/// VST3 modules we found during a serach. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Vst3Module { + /// Old, pre-VST 3.6.10 style `.vst3` modules. These are simply `.dll` files with a different p + /// refix. Even though this is a legacy format, almost all VST3 plugins in the wild still use + /// this format. + Legacy(PathBuf), + /// A VST 3.6.10 bundle, with the same format as the VST3 bundles used on Linux and macOS. + Bundle(PathBuf), +} + impl SearchResults { /// For every found VST2 plugin, find the associated copy or symlink of `libyabridge-vst2.so`. /// The returned hashmap will contain a `None` value for plugins that have not yet been set up. /// /// These two functions could be combined into a single function, but speed isn't really an /// issue here and it's a bit more organized this way. - pub fn installation_status(&self) -> BTreeMap<&Path, Option<&FoundFile>> { - let so_files: HashMap<&Path, &FoundFile> = self + pub fn installation_status(&self) -> BTreeMap<&Path, Option<&NativeSoFile>> { + let so_files: HashMap<&Path, &NativeSoFile> = self .so_files .iter() .map(|file| (file.path(), file)) @@ -71,9 +87,9 @@ impl SearchResults { } /// Find all `.so` files in the search results that do not belong to a VST2 plugin `.dll` file. - pub fn orphans(&self) -> Vec<&FoundFile> { + pub fn orphans(&self) -> Vec<&NativeSoFile> { // We need to store these in a map so we can easily entries with corresponding `.dll` files - let mut orphans: HashMap<&Path, &FoundFile> = self + let mut orphans: HashMap<&Path, &NativeSoFile> = self .so_files .iter() .map(|file| (file.path(), file)) @@ -86,12 +102,12 @@ impl SearchResults { } } -impl FoundFile { +impl NativeSoFile { /// Return the path of a found `.so` file. pub fn path(&self) -> &Path { match &self { - FoundFile::Symlink(path) => path, - FoundFile::Regular(path) => path, + NativeSoFile::Symlink(path) => path, + NativeSoFile::Regular(path) => path, } } } @@ -142,12 +158,14 @@ pub fn index(directory: &Path) -> Result { vst2_files, skipped_files, so_files, + // TODO: Search for VST3 modules + vst3_modules: Vec::new(), }) } /// THe same as [index()](index), but only report found `.so` files. This avoids unnecesarily /// filtering the found `.dll` files. -pub fn index_so_files(directory: &Path) -> Vec { +pub fn index_so_files(directory: &Path) -> Vec { let (_, so_files) = find_files(directory); so_files @@ -155,9 +173,9 @@ pub fn index_so_files(directory: &Path) -> Vec { /// Find all `.dll` and `.so` files under a directory. The results are a pair of `(dll_files, /// so_files)`. -fn find_files(directory: &Path) -> (Vec, Vec) { +fn find_files(directory: &Path) -> (Vec, Vec) { let mut dll_files: Vec = Vec::new(); - let mut so_files: Vec = Vec::new(); + let mut so_files: Vec = Vec::new(); // XXX: We're silently skipping directories and files we don't have permission to read. This // sounds like the expected behavior, but I"m not entirely sure. for (file_idx, entry) in WalkDir::new(directory) @@ -182,9 +200,9 @@ fn find_files(directory: &Path) -> (Vec, Vec) { Some("dll") => dll_files.push(entry.into_path()), Some("so") => { if entry.path_is_symlink() { - so_files.push(FoundFile::Symlink(entry.into_path())); + so_files.push(NativeSoFile::Symlink(entry.into_path())); } else { - so_files.push(FoundFile::Regular(entry.into_path())); + so_files.push(NativeSoFile::Regular(entry.into_path())); } } _ => (),