use std::path::PathBuf;
use std::sync::Mutex;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum InstallScope {
User,
System,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum Format {
Clap,
Vst3,
Vst2,
Lv2,
#[cfg_attr(not(target_os = "macos"), allow(dead_code))]
Au2,
#[cfg_attr(not(target_os = "macos"), allow(dead_code))]
Au3,
#[cfg_attr(not(any(target_os = "macos", target_os = "windows")), allow(dead_code))]
Aax,
}
impl InstallScope {
pub(crate) fn os_default() -> Self {
Self::User
}
pub(crate) fn needs_sudo(self) -> bool {
match self {
Self::User => false,
Self::System => cfg!(target_os = "macos") || cfg!(target_os = "windows"),
}
}
}
#[cfg(any(target_os = "macos", target_os = "windows"))]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum PkgScope {
User,
System,
Ask,
}
#[cfg(any(target_os = "macos", target_os = "windows"))]
impl PkgScope {
pub(crate) fn os_default() -> Self {
Self::Ask
}
pub(crate) fn parse_toml_value(s: &str) -> Result<Self, String> {
match s {
"user" => Ok(Self::User),
"system" => Ok(Self::System),
"ask" => Ok(Self::Ask),
other => Err(format!(
"[packaging] preferred_scope: unknown value {other:?} \
(expected \"user\", \"system\", or \"ask\")"
)),
}
}
pub(crate) fn label(self) -> &'static str {
match self {
Self::User => "user",
Self::System => "system",
Self::Ask => "ask",
}
}
pub(crate) fn dist_suffix(self) -> &'static str {
match self {
Self::User => "-user",
Self::System => "-system",
Self::Ask => "",
}
}
}
pub(crate) fn effective_scope(
format: Format,
requested: InstallScope,
) -> (InstallScope, Option<&'static str>) {
if requested == InstallScope::System {
return (InstallScope::System, None);
}
match format {
Format::Aax => (
InstallScope::System,
Some("AAX is system-only; ignoring --user"),
),
Format::Au3 => (
InstallScope::System,
Some("AU v3 is system-only; ignoring --user"),
),
Format::Vst2 if cfg!(target_os = "windows") => (
InstallScope::System,
Some("VST2 on Windows is system-only; ignoring --user"),
),
_ => (InstallScope::User, None),
}
}
pub(crate) fn note_once(message: &str) {
static SEEN: Mutex<Vec<String>> = Mutex::new(Vec::new());
let mut g = SEEN.lock().unwrap();
if g.iter().any(|s| s == message) {
return;
}
g.push(message.to_string());
eprintln!("note: {message}");
}
#[cfg(any(target_os = "macos", target_os = "linux"))]
fn home() -> PathBuf {
crate::dirs::home_dir().expect("HOME not set")
}
#[cfg(target_os = "windows")]
fn local_appdata() -> PathBuf {
std::env::var_os("LOCALAPPDATA")
.map(PathBuf::from)
.expect("LOCALAPPDATA env var not set")
}
#[cfg(target_os = "windows")]
fn appdata() -> PathBuf {
std::env::var_os("APPDATA")
.map(PathBuf::from)
.expect("APPDATA env var not set")
}
#[cfg(target_os = "macos")]
impl InstallScope {
pub(crate) fn clap_dir(self) -> PathBuf {
match self {
Self::User => home().join("Library/Audio/Plug-Ins/CLAP"),
Self::System => PathBuf::from("/Library/Audio/Plug-Ins/CLAP"),
}
}
pub(crate) fn vst3_dir(self) -> PathBuf {
match self {
Self::User => home().join("Library/Audio/Plug-Ins/VST3"),
Self::System => PathBuf::from("/Library/Audio/Plug-Ins/VST3"),
}
}
pub(crate) fn vst2_dir(self) -> PathBuf {
match self {
Self::User => home().join("Library/Audio/Plug-Ins/VST"),
Self::System => PathBuf::from("/Library/Audio/Plug-Ins/VST"),
}
}
pub(crate) fn lv2_dir(self) -> PathBuf {
match self {
Self::User => home().join("Library/Audio/Plug-Ins/LV2"),
Self::System => PathBuf::from("/Library/Audio/Plug-Ins/LV2"),
}
}
pub(crate) fn au_v2_dir(self) -> PathBuf {
match self {
Self::User => home().join("Library/Audio/Plug-Ins/Components"),
Self::System => PathBuf::from("/Library/Audio/Plug-Ins/Components"),
}
}
}
#[cfg(target_os = "windows")]
impl InstallScope {
pub(crate) fn clap_dir(self) -> PathBuf {
match self {
Self::User => local_appdata().join(r"Programs\Common\CLAP"),
Self::System => crate::common_program_files().join("CLAP"),
}
}
pub(crate) fn vst3_dir(self) -> PathBuf {
match self {
Self::User => local_appdata().join(r"Programs\Common\VST3"),
Self::System => crate::common_program_files().join("VST3"),
}
}
pub(crate) fn vst2_dir(self) -> PathBuf {
crate::program_files().join("Steinberg").join("VstPlugins")
}
pub(crate) fn lv2_dir(self) -> PathBuf {
match self {
Self::User => appdata().join("LV2"),
Self::System => crate::common_program_files().join("LV2"),
}
}
}
#[cfg(target_os = "linux")]
impl InstallScope {
pub(crate) fn clap_dir(self) -> PathBuf {
let _ = self;
home().join(".clap")
}
pub(crate) fn vst3_dir(self) -> PathBuf {
let _ = self;
home().join(".vst3")
}
pub(crate) fn vst2_dir(self) -> PathBuf {
let _ = self;
home().join(".vst")
}
pub(crate) fn lv2_dir(self) -> PathBuf {
let _ = self;
home().join(".lv2")
}
}