From 4d3df70a2e4b93b85b0a808198963de8a8670595 Mon Sep 17 00:00:00 2001 From: jb-alvarado Date: Fri, 14 Jun 2024 10:37:49 +0200 Subject: [PATCH] finish program init --- Cargo.lock | 33 ----- ffplayout/Cargo.toml | 1 - ffplayout/examples/multi_log.rs | 101 -------------- ffplayout/src/db/handles.rs | 21 ++- ffplayout/src/db/models.rs | 8 +- ffplayout/src/main.rs | 6 +- ffplayout/src/player/filter/mod.rs | 2 +- ffplayout/src/player/input/folder.rs | 2 +- ffplayout/src/player/input/ingest.rs | 2 +- ffplayout/src/player/utils/folder.rs | 2 +- ffplayout/src/player/utils/json_serializer.rs | 2 +- ffplayout/src/player/utils/mod.rs | 2 +- ffplayout/src/utils/args_parse.rs | 124 ++++++++++++++---- ffplayout/src/utils/generator.rs | 2 +- ffplayout/src/utils/logging.rs | 9 +- migrations/00001_create_tables.sql | 3 +- 16 files changed, 145 insertions(+), 175 deletions(-) delete mode 100644 ffplayout/examples/multi_log.rs diff --git a/Cargo.lock b/Cargo.lock index eebdcfd6..7af48dfd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1100,7 +1100,6 @@ dependencies = [ "serde_json", "shlex", "signal-child", - "simplelog", "sqlx", "static-files", "sysinfo", @@ -2218,15 +2217,6 @@ dependencies = [ "libc", ] -[[package]] -name = "num_threads" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" -dependencies = [ - "libc", -] - [[package]] name = "object" version = "0.35.0" @@ -2972,18 +2962,6 @@ dependencies = [ "time", ] -[[package]] -name = "simplelog" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16257adbfaef1ee58b1363bdc0664c9b8e1e30aed86049635fb5f147d065a9c0" -dependencies = [ - "log", - "paris", - "termcolor", - "time", -] - [[package]] name = "slab" version = "0.4.9" @@ -3435,15 +3413,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - [[package]] name = "tests" version = "0.24.0" @@ -3497,9 +3466,7 @@ checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", - "libc", "num-conv", - "num_threads", "powerfmt", "serde", "time-core", diff --git a/ffplayout/Cargo.toml b/ffplayout/Cargo.toml index 3b2d68ec..d21c18f9 100644 --- a/ffplayout/Cargo.toml +++ b/ffplayout/Cargo.toml @@ -50,7 +50,6 @@ rpassword = "7.2" sanitize-filename = "0.5" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -simplelog = { version = "0.12", features = ["paris"] } shlex = "1.1" static-files = "0.2" sysinfo ={ version = "0.30", features = ["linux-netdevs"] } diff --git a/ffplayout/examples/multi_log.rs b/ffplayout/examples/multi_log.rs deleted file mode 100644 index d43373b7..00000000 --- a/ffplayout/examples/multi_log.rs +++ /dev/null @@ -1,101 +0,0 @@ -use log::{LevelFilter, Log, Metadata, Record}; -use simplelog::*; -use std::fs::File; - -pub struct LogMailer { - level: LevelFilter, - pub config: Config, -} - -impl LogMailer { - pub fn new(log_level: LevelFilter, config: Config) -> Box { - Box::new(LogMailer { - level: log_level, - config, - }) - } -} - -impl Log for LogMailer { - fn enabled(&self, metadata: &Metadata<'_>) -> bool { - metadata.level() <= self.level - } - - fn log(&self, record: &Record<'_>) { - if self.enabled(record.metadata()) { - let _rec = record.args().to_string(); - - println!("{record:?}"); - println!("target: {:?}", record.target()); - } - } - - fn flush(&self) {} -} - -impl SharedLogger for LogMailer { - fn level(&self) -> LevelFilter { - self.level - } - - fn config(&self) -> Option<&Config> { - Some(&self.config) - } - - fn as_log(self: Box) -> Box { - Box::new(*self) - } -} - -struct Log2 { - logger: Box>, -} - -impl Log2 { - fn new() -> Self { - let log_file = File::create("log_file.log").expect("Failed to create log file"); - - let config = ConfigBuilder::new() - .set_time_format_custom(format_description!( - "[[[year]-[month]-[day] [hour]:[minute]:[second].[subsecond digits:5]]" - )) - .build(); - - let logger = WriteLogger::new(LevelFilter::Debug, config, log_file); - - Log2 { logger } - } - - fn debug(&self, message: &str) { - self.logger.log( - &Record::builder() - .args(format_args!("{}", message)) - .level(Level::Debug) - .build(), - ); - } -} - -fn main() { - let log2 = Log2::new(); - - log2.debug("Debug-Message in Logger 2"); - - // std::thread::spawn(move || { - // log2.debug("Error-Message in Logger 2"); - // }); - - CombinedLogger::init(vec![ - TermLogger::new( - LevelFilter::Debug, - Config::default(), - TerminalMode::Mixed, - ColorChoice::Auto, - ), - LogMailer::new(LevelFilter::Info, Config::default()), - ]) - .unwrap(); - - info!("Info in Logger 1"); - warn!("Warning in Logger 1"); -} diff --git a/ffplayout/src/db/handles.rs b/ffplayout/src/db/handles.rs index 557f026f..8f1ea908 100644 --- a/ffplayout/src/db/handles.rs +++ b/ffplayout/src/db/handles.rs @@ -3,8 +3,8 @@ use argon2::{ Argon2, PasswordHasher, }; +use log::*; use rand::{distributions::Alphanumeric, Rng}; -use simplelog::*; use sqlx::{sqlite::SqliteQueryResult, Pool, Sqlite}; use tokio::task; @@ -40,11 +40,28 @@ pub async fn db_migrate(conn: &Pool) -> Result<&'static str, Box) -> Result { - let query = "SELECT secret, hls_path, playlist_path, storage_path, logging_path FROM global WHERE id = 1"; + let query = "SELECT id, secret, hls_path, logging_path, playlist_path, storage_path, shared_storage FROM global WHERE id = 1"; sqlx::query_as(query).fetch_one(conn).await } +pub async fn update_global( + conn: &Pool, + global: GlobalSettings, +) -> Result { + let query = "UPDATE global SET hls_path = $2, playlist_path = $3, storage_path = $4, logging_path = $5, shared_storage = $6 WHERE id = 1"; + + sqlx::query(query) + .bind(global.id) + .bind(global.hls_path) + .bind(global.playlist_path) + .bind(global.storage_path) + .bind(global.logging_path) + .bind(global.shared_storage) + .execute(conn) + .await +} + pub async fn select_channel(conn: &Pool, id: &i32) -> Result { let query = "SELECT * FROM channels WHERE id = $1"; let mut result: Channel = sqlx::query_as(query).bind(id).fetch_one(conn).await?; diff --git a/ffplayout/src/db/models.rs b/ffplayout/src/db/models.rs index dc08ee5b..4087b969 100644 --- a/ffplayout/src/db/models.rs +++ b/ffplayout/src/db/models.rs @@ -13,11 +13,13 @@ use crate::utils::config::PlayoutConfig; #[derive(Debug, Deserialize, Serialize, sqlx::FromRow)] pub struct GlobalSettings { + pub id: i32, pub secret: Option, pub hls_path: String, + pub logging_path: String, pub playlist_path: String, pub storage_path: String, - pub logging_path: String, + pub shared_storage: bool, } impl GlobalSettings { @@ -27,11 +29,13 @@ impl GlobalSettings { match global_settings.await { Ok(g) => g, Err(_) => GlobalSettings { + id: 0, secret: None, hls_path: String::new(), + logging_path: String::new(), playlist_path: String::new(), storage_path: String::new(), - logging_path: String::new(), + shared_storage: false, }, } } diff --git a/ffplayout/src/main.rs b/ffplayout/src/main.rs index bec70fe6..d55f028d 100644 --- a/ffplayout/src/main.rs +++ b/ffplayout/src/main.rs @@ -79,13 +79,13 @@ async fn main() -> std::io::Result<()> { panic!("{e}"); }; - init_globales(&pool).await; - init_logging(mail_queues.clone())?; - if let Err(c) = run_args(&pool).await { exit(c); } + init_globales(&pool).await; + init_logging(mail_queues.clone())?; + let channel_controllers = Arc::new(Mutex::new(ChannelController::new())); if let Some(conn) = &ARGS.listen { diff --git a/ffplayout/src/player/filter/mod.rs b/ffplayout/src/player/filter/mod.rs index 70876b89..73cb8337 100644 --- a/ffplayout/src/player/filter/mod.rs +++ b/ffplayout/src/player/filter/mod.rs @@ -4,8 +4,8 @@ use std::{ sync::{Arc, Mutex}, }; +use log::*; use regex::Regex; -use simplelog::*; mod custom; pub mod v_drawtext; diff --git a/ffplayout/src/player/input/folder.rs b/ffplayout/src/player/input/folder.rs index bc69cfb8..e2933537 100644 --- a/ffplayout/src/player/input/folder.rs +++ b/ffplayout/src/player/input/folder.rs @@ -9,13 +9,13 @@ use std::{ time::Duration, }; +use log::*; use notify::{ event::{CreateKind, ModifyKind, RemoveKind, RenameMode}, EventKind::{Create, Modify, Remove}, RecursiveMode, Watcher, }; use notify_debouncer_full::new_debouncer; -use simplelog::*; use crate::player::utils::{include_file_extension, Media}; use crate::utils::config::PlayoutConfig; diff --git a/ffplayout/src/player/input/ingest.rs b/ffplayout/src/player/input/ingest.rs index 5d98459b..2fc5a000 100644 --- a/ffplayout/src/player/input/ingest.rs +++ b/ffplayout/src/player/input/ingest.rs @@ -6,7 +6,7 @@ use std::{ }; use crossbeam_channel::Sender; -use simplelog::*; +use log::*; use crate::utils::{ config::{PlayoutConfig, FFMPEG_IGNORE_ERRORS, FFMPEG_UNRECOVERABLE_ERRORS}, diff --git a/ffplayout/src/player/utils/folder.rs b/ffplayout/src/player/utils/folder.rs index 088c67cf..1b4085de 100644 --- a/ffplayout/src/player/utils/folder.rs +++ b/ffplayout/src/player/utils/folder.rs @@ -4,8 +4,8 @@ use std::sync::{ }; use lexical_sort::natural_lexical_cmp; +use log::*; use rand::{seq::SliceRandom, thread_rng}; -use simplelog::*; use walkdir::WalkDir; use crate::player::{ diff --git a/ffplayout/src/player/utils/json_serializer.rs b/ffplayout/src/player/utils/json_serializer.rs index 9d599d99..166c0b11 100644 --- a/ffplayout/src/player/utils/json_serializer.rs +++ b/ffplayout/src/player/utils/json_serializer.rs @@ -6,7 +6,7 @@ use std::{ thread, }; -use simplelog::*; +use log::*; use crate::player::utils::{ get_date, is_remote, json_validate::validate_playlist, modified_time, time_from_header, Media, diff --git a/ffplayout/src/player/utils/mod.rs b/ffplayout/src/player/utils/mod.rs index 64baf44d..a4993b39 100644 --- a/ffplayout/src/player/utils/mod.rs +++ b/ffplayout/src/player/utils/mod.rs @@ -12,12 +12,12 @@ use std::{ use chrono::{prelude::*, TimeDelta}; use ffprobe::{ffprobe, Stream as FFStream}; +use log::*; use rand::prelude::*; use regex::Regex; use reqwest::header; use serde::{de::Deserializer, Deserialize, Serialize}; use serde_json::{json, Map, Value}; -use simplelog::*; pub mod folder; pub mod import; diff --git a/ffplayout/src/utils/args_parse.rs b/ffplayout/src/utils/args_parse.rs index c5c0d733..3b45ae27 100644 --- a/ffplayout/src/utils/args_parse.rs +++ b/ffplayout/src/utils/args_parse.rs @@ -5,11 +5,13 @@ use std::{ }; use clap::Parser; -use log::*; use rpassword::read_password; use sqlx::{Pool, Sqlite}; -use crate::db::{db_pool, handles::insert_user, models::User}; +use crate::db::{ + handles::{self, insert_user}, + models::{GlobalSettings, User}, +}; use crate::utils::config::PlayoutConfig; use crate::ARGS; @@ -62,7 +64,7 @@ pub struct Args { #[clap( long, env, - help = "Override logging level: trace, debug, info, warn, error" + help = "Override logging level: trace, debug, println, warn, eprintln" )] pub log_level: Option, @@ -81,6 +83,9 @@ pub struct Args { #[clap(long, env, help = "Storage root path")] pub storage_path: Option, + #[clap(long, env, help = "Share storage across channels")] + pub shared_storage: bool, + #[clap(short, long, help = "domain name for initialization")] pub domain: Option, @@ -102,7 +107,18 @@ pub async fn run_args(pool: &Pool) -> Result<(), i32> { let mut mail = String::new(); let mut storage = String::new(); let mut playlist = String::new(); + let mut logging = String::new(); let mut hls = String::new(); + let mut shared_store = String::new(); + let mut global = GlobalSettings { + id: 0, + secret: None, + hls_path: String::new(), + playlist_path: String::new(), + storage_path: String::new(), + logging_path: String::new(), + shared_storage: false, + }; print!("Global admin: "); stdout().flush().unwrap(); @@ -136,17 +152,86 @@ pub async fn run_args(pool: &Pool) -> Result<(), i32> { .expect("Did not enter a correct path?"); if storage.trim().is_empty() { - args.storage_path = Some(PathBuf::from("/var/lib/ffplayout/tv-media")); + global.storage_path = "/var/lib/ffplayout/tv-media".to_string(); } else { - args.storage_path = Some(PathBuf::from(storage.trim())); + global.storage_path = storage + .trim() + .trim_matches(|c| c == '"' || c == '\'') + .to_string(); } - println!("{args:?}"); + print!("Playlist path [/var/lib/ffplayout/playlists]: "); + stdout().flush().unwrap(); + + stdin() + .read_line(&mut playlist) + .expect("Did not enter a correct path?"); + + if playlist.trim().is_empty() { + global.playlist_path = "/var/lib/ffplayout/playlists".to_string(); + } else { + global.playlist_path = playlist + .trim() + .trim_matches(|c| c == '"' || c == '\'') + .to_string(); + } + + print!("HLS path [/usr/share/ffplayout/public]: "); + stdout().flush().unwrap(); + + stdin() + .read_line(&mut hls) + .expect("Did not enter a correct path?"); + + if hls.trim().is_empty() { + global.hls_path = "/usr/share/ffplayout/public".to_string(); + } else { + global.hls_path = hls + .trim() + .trim_matches(|c| c == '"' || c == '\'') + .to_string(); + } + + print!("Logging path [/var/log/ffplayout]: "); + stdout().flush().unwrap(); + + stdin() + .read_line(&mut logging) + .expect("Did not enter a correct path?"); + + if logging.trim().is_empty() { + global.logging_path = "/var/log/ffplayout".to_string(); + } else { + global.logging_path = logging + .trim() + .trim_matches(|c| c == '"' || c == '\'') + .to_string(); + } + + print!("Shared storage [Y/n]: "); + stdout().flush().unwrap(); + + stdin() + .read_line(&mut shared_store) + .expect("Did not enter a correct path?"); + + if shared_store.trim().to_lowercase().starts_with('y') { + global.shared_storage = true; + } else { + global.shared_storage = false; + } + + if let Err(e) = handles::update_global(&pool, global).await { + eprintln!("{e}"); + return Err(1); + }; + + println!("Set global settings..."); } if let Some(username) = args.username { if args.mail.is_none() || args.password.is_none() { - error!("Mail/password missing!"); + eprintln!("Mail/password missing!"); return Err(1); } @@ -160,21 +245,12 @@ pub async fn run_args(pool: &Pool) -> Result<(), i32> { token: None, }; - match db_pool().await { - Ok(conn) => { - if let Err(e) = insert_user(&conn, user).await { - error!("{e}"); - return Err(1); - }; - } - - Err(e) => { - error!("{e}"); - return Err(1); - } + if let Err(e) = insert_user(&pool, user).await { + eprintln!("{e}"); + return Err(1); }; - info!("Create admin user \"{username}\" done..."); + println!("Create global admin user \"{username}\" done..."); return Err(0); } @@ -182,11 +258,11 @@ pub async fn run_args(pool: &Pool) -> Result<(), i32> { if let Some(id) = ARGS.dump_config { match PlayoutConfig::dump(&pool, id).await { Ok(_) => { - info!("Dump config to: ffplayout_{id}.toml"); + println!("Dump config to: ffplayout_{id}.toml"); exit(0); } Err(e) => { - error!("Dump config: {e}"); + eprintln!("Dump config: {e}"); exit(1); } @@ -196,11 +272,11 @@ pub async fn run_args(pool: &Pool) -> Result<(), i32> { if let Some(import) = &ARGS.import_config { match PlayoutConfig::import(&pool, import.clone()).await { Ok(_) => { - info!("Import config done..."); + println!("Import config done..."); exit(0); } Err(e) => { - error!("{e}"); + eprintln!("{e}"); exit(1); } diff --git a/ffplayout/src/utils/generator.rs b/ffplayout/src/utils/generator.rs index 2115923d..a6c13cd9 100644 --- a/ffplayout/src/utils/generator.rs +++ b/ffplayout/src/utils/generator.rs @@ -12,8 +12,8 @@ use std::{ use chrono::Timelike; use lexical_sort::{natural_lexical_cmp, StringSort}; +use log::*; use rand::{seq::SliceRandom, thread_rng, Rng}; -use simplelog::*; use walkdir::WalkDir; use crate::player::{ diff --git a/ffplayout/src/utils/logging.rs b/ffplayout/src/utils/logging.rs index 8b32bfba..0efd2be7 100644 --- a/ffplayout/src/utils/logging.rs +++ b/ffplayout/src/utils/logging.rs @@ -21,12 +21,17 @@ use paris::formatter::colorize_string; use super::ARGS; +use crate::db::models::GlobalSettings; use crate::utils::{config::Mail, errors::ProcessError, round_to_nearest_ten}; #[derive(Debug)] pub struct Target; impl Target { + pub fn all() -> &'static str { + "{file,mail,_Default}" + } + pub fn console() -> &'static str { "{console}" } @@ -258,10 +263,12 @@ fn file_formatter( } pub fn log_file_path() -> PathBuf { + let config = GlobalSettings::global(); + let mut log_path = ARGS .log_path .clone() - .unwrap_or(PathBuf::from("/var/log/ffplayout")); + .unwrap_or(PathBuf::from(&config.logging_path)); if !log_path.is_dir() { log_path = env::current_dir().unwrap(); diff --git a/migrations/00001_create_tables.sql b/migrations/00001_create_tables.sql index 1e70fdf7..4be9aa2c 100644 --- a/migrations/00001_create_tables.sql +++ b/migrations/00001_create_tables.sql @@ -6,9 +6,10 @@ CREATE TABLE id INTEGER PRIMARY KEY AUTOINCREMENT, secret TEXT NOT NULL, hls_path TEXT NOT NULL DEFAULT "/usr/share/ffplayout/public", + logging_path TEXT NOT NULL DEFAULT "/var/log/ffplayout", playlist_path TEXT NOT NULL DEFAULT "/var/lib/ffplayout/playlists", storage_path TEXT NOT NULL DEFAULT "/var/lib/ffplayout/tv-media", - logging_path TEXT NOT NULL DEFAULT "/var/log/ffplayout", + shared_storage INTEGER NOT NULL DEFAULT 1, UNIQUE (secret) );