use crate::prelude::*;
use std::process::Command;
#[derive(Options, Clone, Debug, Deserialize, Serialize)]
pub struct SoxOptions {
#[arg(long)]
#[options(default_fn = default_sox_path, default_doc = "Detected based on sox_ng flag")]
pub sox_path: Option<PathBuf>,
#[arg(long)]
#[options(default_fn = default_sox_ng, default_doc = "Detected based on binary name or --version info")]
pub sox_ng: bool,
}
fn default_sox_path(_partial: &SoxOptionsPartial) -> Option<PathBuf> {
if is_docker() {
return Some(PathBuf::from("sox_ng"));
}
None
}
#[expect(
clippy::unnecessary_wraps,
reason = "Options macro default_fn requires Option<T>"
)]
fn default_sox_ng(partial: &SoxOptionsPartial) -> Option<bool> {
if is_docker() {
return Some(true);
}
if let Some(sox_path) = &partial.sox_path {
let file_name = sox_path.file_name().unwrap_or_default().to_string_lossy();
if file_name.contains("sox_ng") {
return Some(true);
}
}
Some(detect_sox_ng())
}
impl OptionsContract for SoxOptions {
type Partial = SoxOptionsPartial;
fn validate(&self, _validator: &mut OptionsValidator) {}
}
static IS_SOX_NG: LazyLock<bool> = LazyLock::new(|| {
let Ok(output) = Command::new(SOX).arg("--version").output() else {
return true;
};
let stdout = String::from_utf8_lossy(&output.stdout);
stdout.contains("SoX_ng")
});
pub(crate) fn detect_sox_ng() -> bool {
*IS_SOX_NG
}