diff --git a/Cargo.lock b/Cargo.lock index 68acbd49..1bff2828 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -217,7 +217,7 @@ dependencies = [ "serde_urlencoded", "smallvec", "socket2", - "time 0.3.12", + "time 0.3.13", "url", ] @@ -308,6 +308,15 @@ dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "android_system_properties" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7ed72e1635e121ca3e79420540282af22da58be50de153d36f81ddc6b83aa9e" +dependencies = [ + "libc", +] + [[package]] name = "argon2" version = "0.4.1" @@ -337,9 +346,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" +checksum = "4b31b87a3367ed04dbcbc252bce3f2a8172fef861d47177524c503c908dff2c6" dependencies = [ "concurrent-queue", "event-listener", @@ -629,10 +638,11 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6127248204b9aba09a362f6c930ef6a78f2c1b2215f8a7b398c06e1083f17af0" +checksum = "3f725f340c3854e3cb3ab736dc21f0cca183303acea3b3ffec30f141503ac8eb" dependencies = [ + "iana-time-zone", "js-sys", "num-integer", "num-traits", @@ -724,7 +734,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05" dependencies = [ "percent-encoding", - "time 0.3.12", + "time 0.3.13", "version_check", ] @@ -987,9 +997,9 @@ dependencies = [ [[package]] name = "email_address" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8684b7c9cb4857dfa1e5b9629ef584ba618c9b93bae60f58cb23f4f271d0468e" +checksum = "b1b32a7a2580c4473f10f66b512c34bdd7d33c5e3473227ca833abdb5afe4809" [[package]] name = "encoding_rs" @@ -1106,8 +1116,9 @@ dependencies = [ "serde_yaml", "shlex", "simplelog", - "time 0.3.12", + "time 0.3.13", "walkdir", + "winapi 0.3.9", ] [[package]] @@ -1557,6 +1568,19 @@ dependencies = [ "tokio-native-tls", ] +[[package]] +name = "iana-time-zone" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1779539f58004e5dba1c1f093d44325ebeb244bfc04b791acdc0aaeca9c04570" +dependencies = [ + "android_system_properties", + "core-foundation", + "js-sys", + "wasm-bindgen", + "winapi 0.3.9", +] + [[package]] name = "idna" version = "0.2.3" @@ -1779,9 +1803,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.127" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" +checksum = "64de3cc433455c14174d42e554d4027ee631c4d046d43e3ecc6efc4636cdc7a7" [[package]] name = "libsqlite3-sys" @@ -2601,18 +2625,18 @@ checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711" [[package]] name = "serde" -version = "1.0.142" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e590c437916fb6b221e1d00df6e3294f3fccd70ca7e92541c475d6ed6ef5fee2" +checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.142" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34b5b8d809babe02f538c2cfec6f2c1ed10804c0e5a6a041a049a4f5588ccc2e" +checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391" dependencies = [ "proc-macro2", "quote", @@ -2700,7 +2724,7 @@ dependencies = [ "num-bigint", "num-traits", "thiserror", - "time 0.3.12", + "time 0.3.13", ] [[package]] @@ -2712,7 +2736,7 @@ dependencies = [ "log", "paris", "termcolor", - "time 0.3.12", + "time 0.3.13", ] [[package]] @@ -2945,12 +2969,11 @@ dependencies = [ [[package]] name = "time" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74b7cc93fc23ba97fde84f7eea56c55d1ba183f495c6715defdfc7b9cb8c870f" +checksum = "db76ff9fa4b1458b3c7f077f3ff9887394058460d21e634355b273aaf11eea45" dependencies = [ "itoa", - "js-sys", "libc", "num_threads", "time-macros", diff --git a/ffplayout-api/Cargo.toml b/ffplayout-api/Cargo.toml index 5f4128cc..ed885efd 100644 --- a/ffplayout-api/Cargo.toml +++ b/ffplayout-api/Cargo.toml @@ -15,7 +15,7 @@ actix-web = "4" actix-web-grants = "3" actix-web-httpauth = "0.6" argon2 = "0.4" -chrono = "0.4.20" +chrono = "0.4" clap = { version = "3.2", features = ["derive"] } derive_more = "0.99" faccess = "0.2" diff --git a/ffplayout-engine/src/main.rs b/ffplayout-engine/src/main.rs index 30c8b386..d696b725 100644 --- a/ffplayout-engine/src/main.rs +++ b/ffplayout-engine/src/main.rs @@ -42,6 +42,8 @@ struct StatusData { /// /// When file not exists we create it, and when it exists we get its values. fn status_file(stat_file: &str, playout_stat: &PlayoutStatus) { + debug!("Status file path: {stat_file}"); + if !PathBuf::from(stat_file).exists() { let data = json!({ "time_shift": 0.0, diff --git a/ffplayout-engine/src/rpc/mod.rs b/ffplayout-engine/src/rpc/mod.rs index b5772ae3..0fb47be2 100644 --- a/ffplayout-engine/src/rpc/mod.rs +++ b/ffplayout-engine/src/rpc/mod.rs @@ -2,7 +2,7 @@ use std::{process::exit, sync::atomic::Ordering}; mod zmq_cmd; -use futures::executor; +use futures::executor::block_on; use jsonrpc_http_server::{ hyper, jsonrpc_core::{IoHandler, Params, Value}, @@ -90,49 +90,32 @@ pub fn json_rpc_server( let mut clips_filter = playout_stat.chain.lock().unwrap(); *clips_filter = vec![filter.clone()]; - let reply = executor::block_on(async { - let mut reply_text = String::new(); + if config.out.mode != "hls" || !proc.server_is_running.load(Ordering::SeqCst) { + let filter_stream = format!( + "Parsed_drawtext_{} reinit {filter}", + playout_stat.drawtext_stream_index.load(Ordering::SeqCst) + ); - if config.out.mode != "hls" - || !proc.server_is_running.load(Ordering::SeqCst) - { - let filter_stream = format!( - "Parsed_drawtext_{} reinit {filter}", - playout_stat.drawtext_stream_index.load(Ordering::SeqCst) - ); + if let Ok(reply) = block_on(zmq_send( + &filter_stream, + &config.text.zmq_stream_socket.clone().unwrap(), + )) { + return Ok(Value::String(reply)); + }; + } - if let Ok(reply) = zmq_send( - &filter_stream, - &config.text.zmq_stream_socket.clone().unwrap(), - ) - .await - { - reply_text = reply; - }; - } + if config.out.mode == "hls" && proc.server_is_running.load(Ordering::SeqCst) { + let filter_server = format!( + "Parsed_drawtext_{} reinit {filter}", + playout_stat.drawtext_server_index.load(Ordering::SeqCst) + ); - if config.out.mode == "hls" && proc.server_is_running.load(Ordering::SeqCst) - { - let filter_server = format!( - "Parsed_drawtext_{} reinit {filter}", - playout_stat.drawtext_server_index.load(Ordering::SeqCst) - ); - - if let Ok(reply) = zmq_send( - &filter_server, - &config.text.zmq_server_socket.clone().unwrap(), - ) - .await - { - reply_text = reply; - }; - } - - reply_text - }); - - if !reply.is_empty() { - return Ok(Value::String(reply)); + if let Ok(reply) = block_on(zmq_send( + &filter_server, + &config.text.zmq_server_socket.clone().unwrap(), + )) { + return Ok(Value::String(reply)); + }; } } diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 0aef4e01..66ed525e 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -8,7 +8,7 @@ version = "0.14.0" edition = "2021" [dependencies] -chrono = "0.4.20" +chrono = "0.4" crossbeam-channel = "0.5" ffprobe = "0.3" file-rotate = "0.7.0" @@ -27,5 +27,13 @@ simplelog = { version = "^0.12", features = ["paris"] } time = { version = "0.3", features = ["formatting", "macros"] } walkdir = "2" +[target."cfg(windows)".dependencies.winapi] +version = "0.3" +features = [ + "shlobj", + "std", + "winerror", +] + [target.x86_64-unknown-linux-musl.dependencies] openssl = { version = "0.10", features = ["vendored"] } diff --git a/lib/src/utils/config.rs b/lib/src/utils/config.rs index 15b403b1..cef1d222 100644 --- a/lib/src/utils/config.rs +++ b/lib/src/utils/config.rs @@ -8,7 +8,7 @@ use std::{ use serde::{Deserialize, Serialize}; use shlex::split; -use crate::utils::{free_tcp_socket, time_to_sec}; +use crate::utils::{free_tcp_socket, home_dir, time_to_sec}; use crate::vec_strings; pub const DUMMY_LEN: f64 = 60.0; @@ -199,8 +199,9 @@ impl PlayoutConfig { let mut config: PlayoutConfig = serde_yaml::from_reader(f).expect("Could not read config file."); config.general.generate = None; - config.general.stat_file = env::temp_dir() - .join("ffplayout_status.json") + config.general.stat_file = home_dir() + .unwrap_or_else(env::temp_dir) + .join(".ffp_status") .display() .to_string(); let bitrate = format!( diff --git a/lib/src/utils/mod.rs b/lib/src/utils/mod.rs index a1385381..7ce02b7a 100644 --- a/lib/src/utils/mod.rs +++ b/lib/src/utils/mod.rs @@ -1,9 +1,10 @@ use std::{ + env, ffi::OsStr, fs::{self, metadata}, io::{BufRead, BufReader, Error}, net::TcpListener, - path::Path, + path::{Path, PathBuf}, process::{ChildStderr, Command, Stdio}, sync::{Arc, Mutex}, time::{self, UNIX_EPOCH}, @@ -27,6 +28,9 @@ pub mod json_serializer; mod json_validate; mod logging; +#[cfg(windows)] +mod windows; + pub use config::{self as playout_config, PlayoutConfig, DUMMY_LEN, IMAGE_FORMAT}; pub use controller::{PlayerControl, PlayoutStatus, ProcessControl, ProcessUnit::*}; pub use generator::generate_playlist; @@ -725,6 +729,19 @@ pub fn free_tcp_socket(exclude_socket: String) -> Option { None } +pub fn home_dir() -> Option { + home_dir_inner() +} + +#[cfg(windows)] +use windows::home_dir_inner; + +#[cfg(any(unix, target_os = "redox"))] +fn home_dir_inner() -> Option { + #[allow(deprecated)] + env::home_dir() +} + /// Get system time, in non test case. #[cfg(not(test))] pub fn time_now() -> DateTime { diff --git a/lib/src/utils/windows.rs b/lib/src/utils/windows.rs new file mode 100644 index 00000000..58aae005 --- /dev/null +++ b/lib/src/utils/windows.rs @@ -0,0 +1,43 @@ +use std::{env, ffi::OsString, os::windows::ffi::OsStringExt, path::PathBuf, ptr}; + +use winapi::shared::minwindef::MAX_PATH; +use winapi::shared::winerror::S_OK; +use winapi::um::shlobj::{SHGetFolderPathW, CSIDL_PROFILE}; + +pub fn home_dir_inner() -> Option { + env::var_os("USERPROFILE") + .filter(|s| !s.is_empty()) + .map(PathBuf::from) + .or_else(home_dir_crt) +} + +#[cfg(not(target_vendor = "uwp"))] +fn home_dir_crt() -> Option { + unsafe { + let mut path: Vec = Vec::with_capacity(MAX_PATH); + match SHGetFolderPathW( + ptr::null_mut(), + CSIDL_PROFILE, + ptr::null_mut(), + 0, + path.as_mut_ptr(), + ) { + S_OK => { + let len = wcslen(path.as_ptr()); + path.set_len(len); + let s = OsString::from_wide(&path); + Some(PathBuf::from(s)) + } + _ => None, + } + } +} + +#[cfg(target_vendor = "uwp")] +fn home_dir_crt() -> Option { + None +} + +extern "C" { + fn wcslen(buf: *const u16) -> usize; +}