diff --git a/Cargo.lock b/Cargo.lock index d40c6e7..7c1586f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -341,6 +341,22 @@ dependencies = [ "termcolor", ] +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" + [[package]] name = "flate2" version = "1.0.28" @@ -484,6 +500,7 @@ dependencies = [ "mpvipc-async", "serde", "serde_json", + "tempfile", "tokio", "tower", "tower-http", @@ -644,6 +661,12 @@ version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + [[package]] name = "lock_api" version = "0.4.11" @@ -922,6 +945,19 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags 2.5.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + [[package]] name = "rustversion" version = "1.0.15" @@ -1050,6 +1086,19 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "tempfile" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.52.0", +] + [[package]] name = "termcolor" version = "1.4.1" diff --git a/Cargo.toml b/Cargo.toml index 3f52df7..e40c614 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ log = "0.4.20" mpvipc-async = { git = "https://git.pvv.ntnu.no/oysteikt/mpvipc-async.git", rev = "v0.1.0" } serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.105" +tempfile = "3.11.0" tokio = { version = "1.32.0", features = ["full"] } tower = { version = "0.4.13", features = ["full"] } tower-http = { version = "0.4.3", features = ["full"] } diff --git a/assets/default-mpv.conf b/assets/default-mpv.conf new file mode 100644 index 0000000..bc08973 --- /dev/null +++ b/assets/default-mpv.conf @@ -0,0 +1,3 @@ +[youtube] +profile-cond=path:find('youtu%.?be') +--ytdl-format="bestvideo[height<=?720][vcodec!~='vp0?9']+bestaudio/best" diff --git a/src/main.rs b/src/main.rs index bbd7a3b..35fb514 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,9 +4,11 @@ use clap::Parser; use mpvipc_async::Mpv; use std::{ fs::create_dir_all, + io::Write, net::{IpAddr, SocketAddr}, path::Path, }; +use tempfile::NamedTempFile; use tokio::process::{Child, Command}; mod api; @@ -25,6 +27,9 @@ struct Args { #[clap(long, value_name = "PATH")] mpv_executable_path: Option, + #[clap(long, value_name = "PATH")] + mpv_config_file: Option, + #[clap(long, default_value = "true")] auto_start_mpv: bool, @@ -32,14 +37,39 @@ struct Args { force_auto_start: bool, } -struct MpvConnectionArgs { +struct MpvConnectionArgs<'a> { socket_path: String, executable_path: Option, + config_file: &'a NamedTempFile, auto_start: bool, force_auto_start: bool, } -async fn connect_to_mpv(args: &MpvConnectionArgs) -> anyhow::Result<(Mpv, Option)> { +const DEFAULT_MPV_CONFIG_CONTENT: &str = include_str!("../assets/default-mpv.conf"); + +fn create_mpv_config_file(args_config_file: Option) -> anyhow::Result { + let file_content = if let Some(path) = args_config_file { + if !Path::new(&path).exists() { + anyhow::bail!("Mpv config file not found at {}", &path); + } + + std::fs::read_to_string(&path).context("Failed to read mpv config file")? + } else { + DEFAULT_MPV_CONFIG_CONTENT.to_string() + }; + + let tmpfile = tempfile::Builder::new() + .prefix("mpv-") + .rand_bytes(8) + .suffix(".conf") + .tempfile()?; + + tmpfile.reopen()?.write_all(file_content.as_bytes())?; + + Ok(tmpfile) +} + +async fn connect_to_mpv<'a>(args: &MpvConnectionArgs<'a>) -> anyhow::Result<(Mpv, Option)> { log::debug!("Connecting to mpv"); debug_assert!( @@ -81,6 +111,11 @@ async fn connect_to_mpv(args: &MpvConnectionArgs) -> anyhow::Result<(Mpv, Option .arg("--idle") .arg("--force-window") .arg("--fullscreen") + .arg("--no-config") + .arg(format!( + "--include={}", + &args.config_file.path().to_string_lossy() + )) // .arg("--no-terminal") .arg("--load-unsafe-playlists") .arg("--keep-open") // Keep last frame of video on end of video @@ -131,9 +166,12 @@ async fn main() -> anyhow::Result<()> { env_logger::init(); let args = Args::parse(); + let mpv_config_file = create_mpv_config_file(args.mpv_config_file)?; + let (mpv, proc) = connect_to_mpv(&MpvConnectionArgs { socket_path: args.mpv_socket_path, executable_path: args.mpv_executable_path, + config_file: &mpv_config_file, auto_start: args.auto_start_mpv, force_auto_start: args.force_auto_start, }) @@ -180,5 +218,7 @@ async fn main() -> anyhow::Result<()> { } } + std::mem::drop(mpv_config_file); + Ok(()) }