tidalcycles_rs/
supercollider_looper.rs

1use std::path::PathBuf;
2use std::process::Command;
3
4/// Ensures the TidalLooper Quark is installed in the user's SuperCollider Quarks directory.
5/// Returns Ok(true) if installed or cloned, Ok(false) if already present, Err if failed.
6pub fn ensure_tidallooper_quark_installed() -> Result<bool, String> {
7    let quarks_dir = dirs::home_dir()
8        .map(|h| h.join(".local/share/SuperCollider/Quarks"))
9        .ok_or("Could not determine home directory")?;
10    let looper_dir = quarks_dir.join("TidalLooper");
11    if looper_dir.exists() {
12        return Ok(false); // Already present
13    }
14    println!("TidalLooper Quark not found, attempting to clone...");
15    let status = Command::new("git")
16        .args(&[
17            "clone",
18            "https://github.com/thgrund/tidal-looper.git",
19            looper_dir.to_str().unwrap(),
20        ])
21        .status();
22    match status {
23        Ok(s) if s.success() => Ok(true),
24        Ok(_) | Err(_) => Err(
25            "Failed to clone TidalLooper Quark. Please install manually if you need live looping."
26                .to_string(),
27        ),
28    }
29}
30
31/// Returns the SuperCollider user Extensions directory (for plugins), e.g. AppData/Local/SuperCollider/Extensions on Windows.
32pub fn get_sc_user_plugins_dir() -> Option<PathBuf> {
33    dirs::home_dir().map(|h| h.join("AppData/Local/SuperCollider/Extensions"))
34}
35
36/// Ensures the TidalLooper Quark is installed in the user's SuperCollider Extensions directory (AppData/Local/SuperCollider/Extensions on Windows).
37/// Returns Ok(true) if installed or cloned, Ok(false) if already present, Err if failed.
38pub fn ensure_tidallooper_in_user_extensions() -> Result<bool, String> {
39    let sc_user_plugins_dir = dirs::home_dir()
40        .ok_or("Could not find home directory")?
41        .join("AppData/Local/SuperCollider/Extensions");
42    let looper_dir = sc_user_plugins_dir.join("tidal-looper");
43    if looper_dir.exists() {
44        return Ok(false); // Already present
45    }
46    println!("TidalLooper not found in Extensions, attempting to clone...");
47    std::fs::create_dir_all(&sc_user_plugins_dir)
48        .map_err(|e| format!("Failed to create Extensions dir: {}", e))?;
49    let status = Command::new("git")
50        .args(&[
51            "clone",
52            "https://github.com/thgrund/tidal-looper.git",
53            looper_dir.to_str().unwrap(),
54        ])
55        .status();
56    match status {
57        Ok(s) if s.success() => Ok(true),
58        Ok(_) | Err(_) => Err("Failed to clone TidalLooper into Extensions. Please install manually if you need live looping.".to_string()),
59    }
60}