mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-09 20:29:10 +02:00
Always search for host in ~/.local/share/yabridge
This commit is contained in:
@@ -8,6 +8,12 @@ Versioning](https://semver.org/spec/v2.0.0.html).
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Yabridge will now always search for `yabridge-host.exe` in
|
||||||
|
`~/.local/share/yabridge`, even if that directory is not in the search path.
|
||||||
|
This should make setup easier.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed an issue where _Renoise_ would show an error message when trying to load
|
- Fixed an issue where _Renoise_ would show an error message when trying to load
|
||||||
|
|||||||
@@ -83,12 +83,12 @@ or by running `yabridgectl --help`.
|
|||||||
|
|
||||||
First, yabridgectl needs to know where it can find yabridge's files. If you have
|
First, yabridgectl needs to know where it can find yabridge's files. If you have
|
||||||
downloaded the prebuilt binaries, then you can simply extract the archive to
|
downloaded the prebuilt binaries, then you can simply extract the archive to
|
||||||
`~/.local/share` and yabridgectl will pick up the files in
|
`~/.local/share` and both yabridge and yabridgectl will pick up the files in
|
||||||
`~/.local/share/yabridge` automatically[\*](#why-local-share-yabridge). You also
|
`~/.local/share/yabridge` automatically. You also won't have to do any
|
||||||
won't have to do any additional work if you're using one of the AUR packages. If
|
additional work if you're using one of the AUR packages. If you have compiled
|
||||||
you have compiled yabridge from source or if you installed the files to some
|
yabridge from source or if you installed the files to some other location, then
|
||||||
other location, then you can use `yabridgectl set --path=<path>` to tell
|
you can use `yabridgectl set --path=<path>` to tell yabridgectl where it can
|
||||||
yabridgectl where it can find the files.
|
find the files.
|
||||||
|
|
||||||
Secondly, yabridgectl will default to the copy-based installation method. If you
|
Secondly, yabridgectl will default to the copy-based installation method. If you
|
||||||
are using a VST host with individually sandboxed plugins such as Bitwig Studio
|
are using a VST host with individually sandboxed plugins such as Bitwig Studio
|
||||||
@@ -107,16 +107,6 @@ tell your VST host to search for plugins in the directories you just added and
|
|||||||
you'll be good to go. _Don't forget to rerun `yabridgectl sync` whenever you
|
you'll be good to go. _Don't forget to rerun `yabridgectl sync` whenever you
|
||||||
update yabridge if you are using the copy-based installation method._
|
update yabridge if you are using the copy-based installation method._
|
||||||
|
|
||||||
<sup id="why-local-share-yabridge">
|
|
||||||
*Instead of copying yabridge's files to <code>~/.local/share</code>, it would
|
|
||||||
also be possible to install yabridge to <code>/usr/local/bin</code> and
|
|
||||||
<code>/usr/local/lib</code>. While this does avoid the need to modify your
|
|
||||||
<code>PATH</code> environment variable when using the copy-based installation
|
|
||||||
method, it could also cause other issues if you're not careful. This is why
|
|
||||||
it's recommended to install yabridge to your home directory if you're not
|
|
||||||
using one of the AUR packages.
|
|
||||||
</sup>
|
|
||||||
|
|
||||||
### Manual setup
|
### Manual setup
|
||||||
|
|
||||||
To set up yabridge without using yabridgectl, first download and extract
|
To set up yabridge without using yabridgectl, first download and extract
|
||||||
@@ -143,15 +133,21 @@ update yabridge.
|
|||||||
|
|
||||||
### Search path setup
|
### Search path setup
|
||||||
|
|
||||||
If you're using the _copy-based_ installation method and you're not using any of
|
This section is only relevant if you're using the _copy-based_ installation
|
||||||
the AUR packages, then you may have to modify your _login shell_'s `PATH`
|
method and your yabridge files are located somewhere other than in
|
||||||
environment variable so that yabridge is able to find the files in the directory
|
`~/.local/share/yabridge`. If you're using one of the AUR packages then you can
|
||||||
you've extracted yabridge's files to. Yabridgectl will automatically check
|
also skip this section.
|
||||||
whether this is set up correctly when you run `yabridgectl sync`, and it will
|
|
||||||
show a warning if it detects any issues. _If you do not see such a warning after
|
|
||||||
running `yabridgectl sync`, then you can skip this section._
|
|
||||||
|
|
||||||
To do this, you'll want to add yabridge's installation directory to your login
|
Yabridge needs to know where it can find `yabridge-host.exe`. By default
|
||||||
|
yabridge will search your through search path as well as in
|
||||||
|
`~/.local/share/yabridge` if that exists. When loading yabridge from a
|
||||||
|
non-standard location, such as when building from source, you may have to modify
|
||||||
|
your _login shell_'s `PATH` environment variable so that yabridge is able to
|
||||||
|
find its files. Yabridgectl will automatically check whether this is set up
|
||||||
|
correctly when you run `yabridgectl sync`, and it will show a warning if it
|
||||||
|
detects any issues. _If you do not see such a warning after running `yabridgectl sync`, then you can skip this section._
|
||||||
|
|
||||||
|
To set this, you'll want to add yabridge's installation directory to your login
|
||||||
shell's `PATH` environment variable. If you're unsure what your login shell is,
|
shell's `PATH` environment variable. If you're unsure what your login shell is,
|
||||||
then you can open a terminal and run `echo $SHELL` to find out. For the below
|
then you can open a terminal and run `echo $SHELL` to find out. For the below
|
||||||
examples I'll assume you're using the default installation location at
|
examples I'll assume you're using the default installation location at
|
||||||
|
|||||||
+16
-1
@@ -118,7 +118,8 @@ fs::path find_vst_host(PluginArchitecture plugin_arch, bool use_plugin_groups) {
|
|||||||
|
|
||||||
// Boost will return an empty path if the file could not be found in the
|
// Boost will return an empty path if the file could not be found in the
|
||||||
// search path
|
// search path
|
||||||
const fs::path vst_host_path = bp::search_path(host_name);
|
const fs::path vst_host_path =
|
||||||
|
bp::search_path(host_name, get_modified_search_path());
|
||||||
if (vst_host_path == "") {
|
if (vst_host_path == "") {
|
||||||
throw std::runtime_error("Could not locate '" + std::string(host_name) +
|
throw std::runtime_error("Could not locate '" + std::string(host_name) +
|
||||||
"'");
|
"'");
|
||||||
@@ -176,6 +177,20 @@ boost::filesystem::path generate_group_endpoint(
|
|||||||
return get_temporary_directory() / socket_name.str();
|
return get_temporary_directory() / socket_name.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<boost::filesystem::path> get_modified_search_path() {
|
||||||
|
std::vector<boost::filesystem::path> search_path =
|
||||||
|
boost::this_process::path();
|
||||||
|
|
||||||
|
const bp::environment environment = boost::this_process::environment();
|
||||||
|
if (auto home_directory = environment.find("HOME");
|
||||||
|
home_directory != environment.end()) {
|
||||||
|
search_path.push_back(fs::path(home_directory->to_string()) / ".local" /
|
||||||
|
"share" / "yabridge");
|
||||||
|
}
|
||||||
|
|
||||||
|
return search_path;
|
||||||
|
}
|
||||||
|
|
||||||
fs::path get_this_file_location() {
|
fs::path get_this_file_location() {
|
||||||
// HACK: Not sure why, but `boost::dll::this_line_location()` returns a path
|
// HACK: Not sure why, but `boost::dll::this_line_location()` returns a path
|
||||||
// starting with a double slash on some systems. I've seen this happen
|
// starting with a double slash on some systems. I've seen this happen
|
||||||
|
|||||||
+12
-1
@@ -80,7 +80,8 @@ PluginArchitecture find_vst_architecture(boost::filesystem::path);
|
|||||||
* when developing, as you can simply symlink the the libyabridge.so
|
* when developing, as you can simply symlink the the libyabridge.so
|
||||||
* file in the build directory without having to install anything to
|
* file in the build directory without having to install anything to
|
||||||
* /usr.
|
* /usr.
|
||||||
* 2. In the regular search path.
|
* 2. In the regular search path, augmented with `~/.local/share/yabridge` to
|
||||||
|
* ease the setup process.
|
||||||
*
|
*
|
||||||
* @param plugin_arch The architecture of the plugin, either 64-bit or 32-bit.
|
* @param plugin_arch The architecture of the plugin, either 64-bit or 32-bit.
|
||||||
* Used to determine which host application to use, if available.
|
* Used to determine which host application to use, if available.
|
||||||
@@ -143,6 +144,16 @@ boost::filesystem::path generate_group_endpoint(
|
|||||||
const boost::filesystem::path& wine_prefix,
|
const boost::filesystem::path& wine_prefix,
|
||||||
const PluginArchitecture architecture);
|
const PluginArchitecture architecture);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the search path as defined in `$PATH`, with `~/.local/share/yabridge`
|
||||||
|
* appended to the end. I'd rather not do this since more magic makes things
|
||||||
|
* harder to comprehend, but I can understand that modifying your login shell's
|
||||||
|
* `PATH` environment variable can be a big hurdle if you've never done anything
|
||||||
|
* like that before. And since this is the recommended installation location, it
|
||||||
|
* makes sense to also search there by default.
|
||||||
|
*/
|
||||||
|
std::vector<boost::filesystem::path> get_modified_search_path();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a path to this `.so` file. This can be used to find out from where
|
* Return a path to this `.so` file. This can be used to find out from where
|
||||||
* this link to or copy of `libyabridge.so` was loaded.
|
* this link to or copy of `libyabridge.so` was loaded.
|
||||||
|
|||||||
Generated
+10
@@ -242,6 +242,15 @@ dependencies = [
|
|||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is_executable"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "302d553b8abc8187beb7d663e34c065ac4570b273bc9511a50e940e99409c577"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kernel32-sys"
|
name = "kernel32-sys"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@@ -704,6 +713,7 @@ dependencies = [
|
|||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
"colored",
|
"colored",
|
||||||
|
"is_executable",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"promptly",
|
"promptly",
|
||||||
"rayon",
|
"rayon",
|
||||||
|
|||||||
@@ -10,10 +10,11 @@ repository = "https://github.com/robbert-vdh/yabridge"
|
|||||||
license = "GPL-3.0-or-later"
|
license = "GPL-3.0-or-later"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.31"
|
|
||||||
aho-corasick = "0.7.13"
|
aho-corasick = "0.7.13"
|
||||||
colored = "2.0.0"
|
anyhow = "1.0.31"
|
||||||
clap = { version = "3.0.0-beta.1", features = ["wrap_help"] }
|
clap = { version = "3.0.0-beta.1", features = ["wrap_help"] }
|
||||||
|
colored = "2.0.0"
|
||||||
|
is_executable = "0.1.2"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
promptly = "0.3.0"
|
promptly = "0.3.0"
|
||||||
rayon = "1.3.1"
|
rayon = "1.3.1"
|
||||||
|
|||||||
@@ -29,15 +29,15 @@ use xdg::BaseDirectories;
|
|||||||
use crate::files::{self, SearchResults};
|
use crate::files::{self, SearchResults};
|
||||||
|
|
||||||
/// The name of the config file, relative to `$XDG_CONFIG_HOME/CONFIG_PREFIX`.
|
/// The name of the config file, relative to `$XDG_CONFIG_HOME/CONFIG_PREFIX`.
|
||||||
const CONFIG_FILE_NAME: &str = "config.toml";
|
pub const CONFIG_FILE_NAME: &str = "config.toml";
|
||||||
/// The name of the XDG base directory prefix for yabridgectl, relative to `$XDG_CONFIG_HOME` and
|
/// The name of the XDG base directory prefix for yabridgectl, relative to `$XDG_CONFIG_HOME` and
|
||||||
/// `$XDG_DATA_HOME`.
|
/// `$XDG_DATA_HOME`.
|
||||||
const YABRIDGECTL_PREFIX: &str = "yabridgectl";
|
const YABRIDGECTL_PREFIX: &str = "yabridgectl";
|
||||||
|
|
||||||
/// The name of the library file we're searching for.
|
/// The name of the library file we're searching for.
|
||||||
const LIBYABRIDGE_NAME: &str = "libyabridge.so";
|
pub const LIBYABRIDGE_NAME: &str = "libyabridge.so";
|
||||||
/// The name of the script we're going to run to verify that everything's working correctly.
|
/// The name of the script we're going to run to verify that everything's working correctly.
|
||||||
const YABRIDGE_HOST_EXE_NAME: &str = "yabridge-host.exe";
|
pub const YABRIDGE_HOST_EXE_NAME: &str = "yabridge-host.exe";
|
||||||
/// The name of the XDG base directory prefix for yabridge's own files, relative to
|
/// The name of the XDG base directory prefix for yabridge's own files, relative to
|
||||||
/// `$XDG_CONFIG_HOME` and `$XDG_DATA_HOME`.
|
/// `$XDG_CONFIG_HOME` and `$XDG_DATA_HOME`.
|
||||||
const YABRIDGE_PREFIX: &str = "yabridge";
|
const YABRIDGE_PREFIX: &str = "yabridge";
|
||||||
@@ -191,8 +191,8 @@ impl Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Err(anyhow!(
|
Err(anyhow!(
|
||||||
"Could not find '{}' in either '{}' or '{}'. You can tell yabridgectl where \
|
"Could not find '{}' in either '{}' or '{}'. You can override the default \
|
||||||
to search for it using 'yabridgectl set --path=<path>'.",
|
search path using 'yabridgectl set --path=<path>'.",
|
||||||
LIBYABRIDGE_NAME,
|
LIBYABRIDGE_NAME,
|
||||||
system_path.display(),
|
system_path.display(),
|
||||||
user_path.display()
|
user_path.display()
|
||||||
@@ -229,12 +229,12 @@ impl Config {
|
|||||||
/// Fetch the XDG base directories for yabridge's own files, converting any error messages if this
|
/// Fetch the XDG base directories for yabridge's own files, converting any error messages if this
|
||||||
/// somehow fails into a printable string to reduce boiler plate. This is only used when searching
|
/// somehow fails into a printable string to reduce boiler plate. This is only used when searching
|
||||||
/// for `libyabridge.so` when no explicit search path has been set.
|
/// for `libyabridge.so` when no explicit search path has been set.
|
||||||
fn yabridge_directories() -> Result<BaseDirectories> {
|
pub fn yabridge_directories() -> Result<BaseDirectories> {
|
||||||
BaseDirectories::with_prefix(YABRIDGE_PREFIX).context("Error while parsing base directories")
|
BaseDirectories::with_prefix(YABRIDGE_PREFIX).context("Error while parsing base directories")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fetch the XDG base directories used for yabridgectl, converting any error messages if this
|
/// Fetch the XDG base directories used for yabridgectl, converting any error messages if this
|
||||||
/// somehow fails into a printable string to reduce boiler plate.
|
/// somehow fails into a printable string to reduce boiler plate.
|
||||||
fn yabridgectl_directories() -> Result<BaseDirectories> {
|
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")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::{app_from_crate, App, AppSettings, Arg};
|
use clap::{app_from_crate, App, AppSettings, Arg};
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
|
use std::env;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
@@ -27,6 +28,17 @@ mod files;
|
|||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
|
// We'll modify our `PATH` environment variable so it matches up with
|
||||||
|
// `get_modified_search_path()` from `src/plugin/utils.h` for easier setup
|
||||||
|
let yabridge_home = config::yabridge_directories()?.get_data_home();
|
||||||
|
env::set_var(
|
||||||
|
"PATH",
|
||||||
|
match env::var("PATH") {
|
||||||
|
Ok(path) => format!("{}:{}", path, yabridge_home.display()),
|
||||||
|
_ => format!("{}", yabridge_home.display()),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
let mut config = Config::read()?;
|
let mut config = Config::read()?;
|
||||||
|
|
||||||
// Used for validation in `yabridgectl rm <path>`
|
// Used for validation in `yabridgectl rm <path>`
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
|
use is_executable::IsExecutable;
|
||||||
use std::collections::hash_map::DefaultHasher;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
@@ -28,7 +29,7 @@ use std::path::Path;
|
|||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
use textwrap::Wrapper;
|
use textwrap::Wrapper;
|
||||||
|
|
||||||
use crate::config::{Config, KnownConfig};
|
use crate::config::{self, Config, KnownConfig, YABRIDGE_HOST_EXE_NAME};
|
||||||
|
|
||||||
/// (Part of) the expected output when running `yabridge-host.exe`. Used to verify that everything's
|
/// (Part of) the expected output when running `yabridge-host.exe`. Used to verify that everything's
|
||||||
/// working correctly. We'll only match this prefix so we can modify the exact output at a later
|
/// working correctly. We'll only match this prefix so we can modify the exact output at a later
|
||||||
@@ -82,15 +83,33 @@ pub fn hash_file(file: &Path) -> Result<i64> {
|
|||||||
Ok(hasher.finish() as i64)
|
Ok(hasher.finish() as i64)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Verify that `yabridge-host.exe` is accessible in a login shell. Returns unit if it is, or if we
|
/// Verify that `yabridge-host.exe` can be found when yabridge is run in a host launched from the
|
||||||
/// the login shell is set to an unknown shell. In the last case we'll just print a warning since we
|
/// GUI. We do this by launching a login shell, appending `~/.local/share/yabridge` to the login
|
||||||
/// don't know how to invoke the shell as a login shell. This is needed when using copies to ensure
|
/// shell's search path since that's what yabridge also does, and then making the the file can be
|
||||||
/// that yabridge can find the host binaries when the VST host is launched from the desktop
|
/// found. Returns unit if it can be found, or if we the login shell is set to an unknown shell. In
|
||||||
/// enviornment.
|
/// the last case we'll just print a warning since we don't know how to invoke the shell as a login
|
||||||
|
/// shell. This is needed when using copies to ensure that yabridge can find the host binaries when
|
||||||
|
/// the VST host is launched from the desktop enviornment.
|
||||||
///
|
///
|
||||||
/// When we could not find `yabridge-host.exe`, we'll return `Err(shell_name)` so we can print a
|
/// When we could not find `yabridge-host.exe`, we'll return `Err(shell_name)` so we can print a
|
||||||
/// descriptive warning message.
|
/// descriptive warning message.
|
||||||
pub fn verify_path_setup() -> Result<(), String> {
|
pub fn verify_path_setup() -> Result<(), String> {
|
||||||
|
// First we'll check `~/.local/share/yabridge`, since that's a special location where yabridge
|
||||||
|
// will always search
|
||||||
|
if config::yabridge_directories()
|
||||||
|
.ok()
|
||||||
|
.and_then(|dirs| {
|
||||||
|
dirs.get_data_home()
|
||||||
|
.push(YABRIDGE_HOST_EXE_NAME)
|
||||||
|
.is_executable()
|
||||||
|
})
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then we'll check the login shell, since DAWs launched from the GUI will have the same
|
||||||
|
// environment
|
||||||
match env::var("SHELL") {
|
match env::var("SHELL") {
|
||||||
Ok(shell_path) => {
|
Ok(shell_path) => {
|
||||||
// `$SHELL` will often contain a full path, but it doesn't have to
|
// `$SHELL` will often contain a full path, but it doesn't have to
|
||||||
@@ -113,13 +132,20 @@ pub fn verify_path_setup() -> Result<(), String> {
|
|||||||
| "zsh" => command
|
| "zsh" => command
|
||||||
.arg("-l")
|
.arg("-l")
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
.arg("command -v yabridge-host.exe"),
|
.arg(format!("command -v {}", YABRIDGE_HOST_EXE_NAME)),
|
||||||
// These shells either have their own implementation of `which` and don't support
|
// These shells either have their own implementation of `which` and don't support
|
||||||
// `command`, or they don't have a seperate login shell flag
|
// `command`, or they don't have a seperate login shell flag
|
||||||
"elvish" | "oil" => command.arg("-c").arg("command -v yabridge-host.exe"),
|
"elvish" | "oil" => command
|
||||||
|
.arg("-c")
|
||||||
|
.arg(format!("command -v {}", YABRIDGE_HOST_EXE_NAME)),
|
||||||
// xonsh's which implementation is broken as of writing this, so I left it out
|
// xonsh's which implementation is broken as of writing this, so I left it out
|
||||||
"pwsh" => command.arg("-l").arg("-c").arg("which yabridge-host.exe"),
|
"pwsh" => command
|
||||||
"nu" => command.arg("-c").arg("which yabridge-host.exe"),
|
.arg("-l")
|
||||||
|
.arg("-c")
|
||||||
|
.arg(format!("which {}", YABRIDGE_HOST_EXE_NAME)),
|
||||||
|
"nu" => command
|
||||||
|
.arg("-c")
|
||||||
|
.arg(format!("which {}", YABRIDGE_HOST_EXE_NAME)),
|
||||||
shell => {
|
shell => {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"\n{}",
|
"\n{}",
|
||||||
|
|||||||
Reference in New Issue
Block a user