diff --git a/src/common/deps.rs b/src/common/deps.rs index 7af8a35..8bc7f00 100644 --- a/src/common/deps.rs +++ b/src/common/deps.rs @@ -1,5 +1,6 @@ use anyhow::{Result, bail}; use std::path::PathBuf; +use std::process::Command; use crate::common::display::DisplayServer; @@ -7,6 +8,8 @@ pub fn check_host_binaries(display: DisplayServer) -> Result<()> { require("ffmpeg")?; if display == DisplayServer::Wayland { require("gst-launch-1.0")?; + require("gst-inspect-1.0")?; + require_gst_element("pipewiresrc")?; } Ok(()) } @@ -14,13 +17,25 @@ pub fn check_host_binaries(display: DisplayServer) -> Result<()> { fn require(bin: &str) -> Result { match which(bin) { Some(p) => Ok(p), - None => { - let hint = install_hint(bin); - bail!("`{bin}` not found on PATH.\n{hint}"); - } + None => bail!("`{bin}` not found on PATH.\n{}", install_hint_for_bin(bin)), } } +fn require_gst_element(name: &str) -> Result<()> { + let ok = Command::new("gst-inspect-1.0") + .args(["--exists", name]) + .status() + .map(|s| s.success()) + .unwrap_or(false); + if !ok { + bail!( + "GStreamer element `{name}` not available.\n{}", + install_hint_for_gst_element(name) + ); + } + Ok(()) +} + fn which(bin: &str) -> Option { let path = std::env::var_os("PATH")?; for dir in std::env::split_paths(&path) { @@ -32,19 +47,37 @@ fn which(bin: &str) -> Option { None } -fn install_hint(bin: &str) -> String { +fn install_hint_for_bin(bin: &str) -> String { let distro = detect_distro(); let pkg = match bin { "ffmpeg" => "ffmpeg", - "gst-launch-1.0" => match distro.as_deref() { - Some("arch" | "cachyos" | "manjaro" | "endeavouros") => "gst-plugins-base gst-plugins-good", - Some("debian" | "ubuntu" | "pop" | "linuxmint") => "gstreamer1.0-tools gstreamer1.0-plugins-good", - Some("fedora" | "nobara") => "gstreamer1-plugins-good", - _ => "gstreamer (and tools / good-plugins)", + "gst-launch-1.0" | "gst-inspect-1.0" => match distro.as_deref() { + Some("arch" | "cachyos" | "manjaro" | "endeavouros") => "gstreamer gst-plugins-base", + Some("debian" | "ubuntu" | "pop" | "linuxmint") => "gstreamer1.0-tools", + Some("fedora" | "nobara") => "gstreamer1 gstreamer1-plugins-base-tools", + _ => "gstreamer + tools", }, _ => bin, }; + install_command(&distro, pkg) +} +fn install_hint_for_gst_element(name: &str) -> String { + let distro = detect_distro(); + let pkg = match name { + "pipewiresrc" => match distro.as_deref() { + Some("arch" | "cachyos" | "manjaro" | "endeavouros") => "gst-plugin-pipewire", + Some("debian" | "ubuntu" | "pop" | "linuxmint") => "gstreamer1.0-pipewire", + Some("fedora" | "nobara") => "pipewire-gstreamer", + Some("opensuse" | "opensuse-tumbleweed" | "opensuse-leap") => "pipewire-gstreamer", + _ => "the GStreamer PipeWire plugin", + }, + _ => name, + }; + install_command(&distro, pkg) +} + +fn install_command(distro: &Option, pkg: &str) -> String { let cmd = match distro.as_deref() { Some("arch" | "cachyos" | "manjaro" | "endeavouros") => format!("sudo pacman -S {pkg}"), Some("debian" | "ubuntu" | "pop" | "linuxmint") => format!("sudo apt install {pkg}"), @@ -52,7 +85,6 @@ fn install_hint(bin: &str) -> String { Some("opensuse" | "opensuse-tumbleweed" | "opensuse-leap") => format!("sudo zypper install {pkg}"), _ => format!("install the `{pkg}` package via your distro's package manager"), }; - format!("Install hint: {cmd}") }