[yabridgectl] Convert VST 3.7.5 moduleinfo files

This commit is contained in:
Robbert van der Helm
2022-05-20 01:03:27 +02:00
parent cb0c673f58
commit 4a845ec952
4 changed files with 74 additions and 0 deletions
+2
View File
@@ -96,6 +96,8 @@ Versioning](https://semver.org/spec/v2.0.0.html).
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
distro packaged version of yabridge.
- Added support for the new VST 3.7.5 `moduleinfo.json` format to allow
VST3 plugins to replace other VST3 and VST2 plugins with different class IDs.
- `yabridgectl status` now shows the locations where bridged VST2 and VST3
plugins will be set up.
- `yabridgectl sync --prune` now also considers broken symlinks.
+32
View File
@@ -29,6 +29,7 @@ use crate::config::{
use crate::files::{self, NativeFile, Plugin, Vst2Plugin};
use crate::utils::{self, get_file_type};
use crate::utils::{verify_path_setup, verify_wine_setup};
use crate::vst3_moduleinfo::ModuleInfo;
pub mod blacklist;
@@ -471,6 +472,37 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> {
managed_vst3_bundle_files.insert(target_resources_dir);
}
// If the plugin has a VST 3.7.10 moduleinfo file, then we'll rewrite the byte
// orders of the class IDs stored within the file and then write it to the
// bridged VST3 bundle.
// https://steinbergmedia.github.io/vst3_dev_portal/pages/Technical+Documentation/VST+Module+Architecture/ModuleInfo-JSON.html
if let Some(original_moduleinfo_path) = module.original_moduleinfo_path() {
let target_moduleinfo_path = module.target_moduleinfo_path();
let result = utils::read_to_string(&original_moduleinfo_path)
.and_then(|module_info_json| {
serde_jsonrc::from_str(&module_info_json)
.context("Could not parse JSON file")
})
.and_then(|mut module_info: ModuleInfo| {
module_info.rewrite_uid_byte_orders()?;
Ok(module_info)
})
.and_then(|converted_module_info| {
let converted_json =
serde_jsonrc::to_string_pretty(&converted_module_info)
.context("Could not format JSON file")?;
utils::write(target_moduleinfo_path, converted_json)
});
if let Err(error) = result {
eprintln!(
"Error converting '{}', skipping...\n{}",
original_moduleinfo_path.display(),
error
);
}
}
module.original_path().to_path_buf()
}
};
+27
View File
@@ -217,6 +217,24 @@ impl Vst3Module {
}
}
/// Return the path to the Windows plugin's `moduleinfo.json` file if this is a bundle-style
/// plugin and the plugin has one. This file would need to be rewritten using
/// `ModuleInfo::rewrite_uid_byte_orders()` first.
pub fn original_moduleinfo_path(&self) -> Option<PathBuf> {
match &self.module {
Vst3ModuleType::Bundle(bundle_home) => {
let mut path = bundle_home.join("Contents");
path.push("moduleinfo.json");
if path.exists() {
Some(path)
} else {
None
}
}
Vst3ModuleType::Legacy(_) => None,
}
}
/// Get the path to the bundle in `~/.vst3` corresponding to the bridged version of this module.
/// We will try to recreate the original subdirectory structure so plugins are still grouped by
/// manufacturer.
@@ -283,6 +301,15 @@ impl Vst3Module {
path
}
/// If the Windows VST3 plugin had a `moduleinfo.json` file, then it should be translated using
/// `ModuleInfo::rewrite_uid_byte_orders()` and then written to this path.
pub fn target_moduleinfo_path(&self) -> PathBuf {
let mut path = self.target_bundle_home();
path.push("Contents");
path.push("moduleinfo.json");
path
}
/// Get a textual representation of the module type. Used in `yabridgectl status`.
pub fn type_str(&self) -> &str {
match &self.module {
+13
View File
@@ -61,6 +61,13 @@ pub fn create_dir_all<P: AsRef<Path>>(path: P) -> Result<()> {
})
}
/// Wrapper around [`std::fs::read_to_string()`](std::fs::read_to_string) with a human readable
/// error message.
pub fn read_to_string<P: AsRef<Path>>(path: P) -> Result<String> {
fs::read_to_string(&path)
.with_context(|| format!("Could not read file '{}'", path.as_ref().display()))
}
/// Wrapper around [`std::fs::remove_dir_all()`](std::fs::remove_dir_all) with a human readable
/// error message.
pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> Result<()> {
@@ -87,6 +94,12 @@ pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> Result<()> {
})
}
/// Wrapper around [`std::fs::write()`](std::fs::write) with a human readable error message.
pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> Result<()> {
fs::write(&path, contents)
.with_context(|| format!("Could write to '{}'", path.as_ref().display()))
}
/// Get the architecture of the ELF file at `path`. This detection is a bit naive, but we'd rather
/// not depend on `libmagic` or `libreadelf` just for this, since encountering a 32-bit yabridge
/// library is going to be incredibly rare.