Skip to main content

maolan_plugin_host/
paths.rs

1use std::path::PathBuf;
2
3pub fn home_dir() -> String {
4    std::env::var("HOME")
5        .or_else(|_| std::env::var("USERPROFILE"))
6        .unwrap_or_default()
7}
8
9pub fn push_macos_audio_plugin_roots(roots: &mut Vec<PathBuf>, plugin_dir_name: &str) {
10    roots.push(PathBuf::from(format!(
11        "/Library/Audio/Plug-Ins/{plugin_dir_name}"
12    )));
13    roots.push(PathBuf::from(format!(
14        "{}/Library/Audio/Plug-Ins/{plugin_dir_name}",
15        home_dir()
16    )));
17}
18
19pub fn push_unix_plugin_roots(roots: &mut Vec<PathBuf>, plugin_dir_name: &str) {
20    roots.push(PathBuf::from(format!("/usr/lib/{plugin_dir_name}")));
21    roots.push(PathBuf::from(format!("/usr/lib64/{plugin_dir_name}")));
22    roots.push(PathBuf::from(format!("/usr/local/lib/{plugin_dir_name}")));
23    roots.push(PathBuf::from(format!("/usr/local/lib64/{plugin_dir_name}")));
24    roots.push(PathBuf::from(format!("{}/.{plugin_dir_name}", home_dir())));
25    roots.push(PathBuf::from(format!(
26        "{}/.local/lib/{plugin_dir_name}",
27        home_dir()
28    )));
29}
30
31pub fn push_windows_vst3_roots(roots: &mut Vec<PathBuf>) {
32    roots.push(PathBuf::from(r"C:\Program Files\Common Files\VST3"));
33    roots.push(PathBuf::from(r"C:\Program Files (x86)\Common Files\VST3"));
34}
35
36pub fn push_windows_clap_roots(roots: &mut Vec<PathBuf>) {
37    if let Ok(common) = std::env::var("COMMONPROGRAMFILES") {
38        roots.push(PathBuf::from(common).join("CLAP"));
39    }
40    if let Ok(common_x86) = std::env::var("COMMONPROGRAMFILES(X86)") {
41        roots.push(PathBuf::from(common_x86).join("CLAP"));
42    }
43    if let Ok(local_app_data) = std::env::var("LOCALAPPDATA") {
44        roots.push(PathBuf::from(local_app_data).join(r"Programs\Common\CLAP"));
45    }
46}
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51    use std::sync::{LazyLock, Mutex};
52
53    static ENV_GUARD: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
54
55    #[test]
56    fn home_dir_prefers_home_over_userprofile() {
57        let _guard = ENV_GUARD.lock().expect("lock env guard");
58        let old_home = std::env::var("HOME").ok();
59        let old_userprofile = std::env::var("USERPROFILE").ok();
60
61        unsafe {
62            std::env::set_var("HOME", "/home/tester");
63            std::env::set_var("USERPROFILE", "C:/Users/tester");
64        }
65
66        let home = home_dir();
67
68        if let Some(value) = old_home {
69            unsafe { std::env::set_var("HOME", value) };
70        } else {
71            unsafe { std::env::remove_var("HOME") };
72        }
73        if let Some(value) = old_userprofile {
74            unsafe { std::env::set_var("USERPROFILE", value) };
75        } else {
76            unsafe { std::env::remove_var("USERPROFILE") };
77        }
78
79        assert_eq!(home, "/home/tester");
80    }
81
82    #[test]
83    fn push_unix_plugin_roots_adds_system_and_user_locations() {
84        let _guard = ENV_GUARD.lock().expect("lock env guard");
85        let old_home = std::env::var("HOME").ok();
86        unsafe {
87            std::env::set_var("HOME", "/home/tester");
88        }
89
90        let mut roots = Vec::new();
91        push_unix_plugin_roots(&mut roots, "clap");
92
93        if let Some(value) = old_home {
94            unsafe { std::env::set_var("HOME", value) };
95        } else {
96            unsafe { std::env::remove_var("HOME") };
97        }
98
99        assert_eq!(
100            roots,
101            vec![
102                PathBuf::from("/usr/lib/clap"),
103                PathBuf::from("/usr/lib64/clap"),
104                PathBuf::from("/usr/local/lib/clap"),
105                PathBuf::from("/usr/local/lib64/clap"),
106                PathBuf::from("/home/tester/.clap"),
107                PathBuf::from("/home/tester/.local/lib/clap"),
108            ]
109        );
110    }
111
112    #[test]
113    fn push_windows_vst3_roots_adds_standard_locations() {
114        let mut roots = Vec::new();
115
116        push_windows_vst3_roots(&mut roots);
117
118        assert_eq!(
119            roots,
120            vec![
121                PathBuf::from(r"C:\Program Files\Common Files\VST3"),
122                PathBuf::from(r"C:\Program Files (x86)\Common Files\VST3"),
123            ]
124        );
125    }
126
127    #[test]
128    fn push_windows_clap_roots_adds_standard_locations() {
129        let _guard = ENV_GUARD.lock().expect("lock env guard");
130        let old_common = std::env::var("COMMONPROGRAMFILES").ok();
131        let old_common_x86 = std::env::var("COMMONPROGRAMFILES(X86)").ok();
132        let old_local_app_data = std::env::var("LOCALAPPDATA").ok();
133
134        unsafe {
135            std::env::set_var("COMMONPROGRAMFILES", r"C:\Program Files\Common Files");
136            std::env::set_var(
137                "COMMONPROGRAMFILES(X86)",
138                r"C:\Program Files (x86)\Common Files",
139            );
140            std::env::set_var("LOCALAPPDATA", r"C:\Users\tester\AppData\Local");
141        }
142
143        let mut roots = Vec::new();
144        push_windows_clap_roots(&mut roots);
145
146        if let Some(value) = old_common {
147            unsafe { std::env::set_var("COMMONPROGRAMFILES", value) };
148        } else {
149            unsafe { std::env::remove_var("COMMONPROGRAMFILES") };
150        }
151        if let Some(value) = old_common_x86 {
152            unsafe { std::env::set_var("COMMONPROGRAMFILES(X86)", value) };
153        } else {
154            unsafe { std::env::remove_var("COMMONPROGRAMFILES(X86)") };
155        }
156        if let Some(value) = old_local_app_data {
157            unsafe { std::env::set_var("LOCALAPPDATA", value) };
158        } else {
159            unsafe { std::env::remove_var("LOCALAPPDATA") };
160        }
161
162        assert_eq!(
163            roots,
164            vec![
165                PathBuf::from(r"C:\Program Files\Common Files").join("CLAP"),
166                PathBuf::from(r"C:\Program Files (x86)\Common Files").join("CLAP"),
167                PathBuf::from(r"C:\Users\tester\AppData\Local").join(r"Programs\Common\CLAP"),
168            ]
169        );
170    }
171}