diff --git a/Cargo.lock b/Cargo.lock index c29d899..2f9c190 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -529,11 +529,13 @@ name = "gst_pipeline_studio" version = "0.3.4" dependencies = [ "anyhow", + "chrono", "futures-channel", "futures-executor", "gst-plugin-gtk4", "gstreamer", "gtk4", + "lazy_static", "log 0.4.14", "once_cell", "serde", @@ -764,6 +766,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.137" diff --git a/Cargo.toml b/Cargo.toml index e778f43..2c3050c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,8 @@ serde = "1.0" serde_any = "0.5" simplelog = "0.11.2" futures-channel = "0.3" +lazy_static = "1.4" +chrono = "0.4" [dev-dependencies] futures-executor = "0.3" diff --git a/src/app.rs b/src/app.rs index 07f0474..c2f026a 100644 --- a/src/app.rs +++ b/src/app.rs @@ -457,15 +457,18 @@ impl GPSApp { let (ready_tx, ready_rx) = glib::MainContext::channel(glib::Priority::DEFAULT); let app_weak = self.downgrade(); logger::init_logger( - ready_tx, + ready_tx.clone(), Settings::log_file_path() .to_str() .expect("Unable to convert log file path to a string"), ); - GPSUI::logger::setup_logger_list(self); - let _ = ready_rx.attach(None, move |msg: String| { + logger::init_msg_logger(ready_tx); + GPSUI::logger::setup_logger_list(self, "treeview-app-logger", logger::LogType::App); + GPSUI::logger::setup_logger_list(self, "treeview-msg-logger", logger::LogType::Message); + GPSUI::logger::setup_logger_list(self, "treeview-gst-logger", logger::LogType::Gst); + let _ = ready_rx.attach(None, move |msg: (logger::LogType, String)| { let app = upgrade_weak!(app_weak, glib::ControlFlow::Break); - GPSUI::logger::add_to_logger_list(&app, &msg); + GPSUI::logger::add_to_logger_list(&app, msg.0, &msg.1); glib::ControlFlow::Continue }); diff --git a/src/gps/player.rs b/src/gps/player.rs index 3d1bc10..0373392 100644 --- a/src/gps/player.rs +++ b/src/gps/player.rs @@ -279,6 +279,7 @@ impl Player { fn on_pipeline_message(&self, msg: &gst::MessageRef) { use gst::MessageView; + GPS_MSG!("{:?}", msg.structure()); match msg.view() { MessageView::Eos(_) => { GPS_INFO!("EOS received"); diff --git a/src/logger.rs b/src/logger.rs index 1b60e84..306bb78 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -14,6 +14,13 @@ use std::io; use std::fs::File; +use chrono::Local; +use std::sync::Mutex; + +lazy_static::lazy_static! { + static ref MSG_LOGGER: Mutex> = Mutex::new(None); +} + #[derive(Debug, Eq, Ord, PartialEq, PartialOrd)] pub enum LogLevel { @@ -25,6 +32,13 @@ pub enum LogLevel { Trace, } +#[derive(Debug, Clone, PartialEq)] +pub enum LogType { + App, + Gst, + Message, +} + impl LogLevel { pub fn from_u32(value: u32) -> LogLevel { match value { @@ -77,6 +91,22 @@ macro_rules! GPS_DEBUG ( }) ); +#[macro_export] +macro_rules! GPS_MSG ( + () => ($crate::print!("\n")); + ($($arg:tt)*) => ({ + logger::pring_msg_logger(logger::LogType::Message, format_args!($($arg)*).to_string()); + }) +); + +#[macro_export] +macro_rules! GPS_GST_LOG ( + () => ($crate::print!("\n")); + ($($arg:tt)*) => ({ + logger::pring_msg_logger(logger::LogType::Gst, format_args!($($arg)*).to_string()); + }) +); + #[macro_export] macro_rules! GPS_TRACE ( () => ($crate::print!("\n")); @@ -86,7 +116,7 @@ macro_rules! GPS_TRACE ( ); struct WriteAdapter { - sender: Sender, + sender: Sender<(LogType, String)>, buffer: String, } @@ -97,7 +127,9 @@ impl io::Write for WriteAdapter { .push_str(&String::from_utf8(buf.to_vec()).unwrap()); if self.buffer.ends_with('\n') { self.buffer.pop(); - self.sender.send(self.buffer.clone()).unwrap(); + self.sender + .send((LogType::App, self.buffer.clone())) + .unwrap(); self.buffer = String::from(""); } @@ -120,7 +152,7 @@ fn translate_to_simple_logger(log_level: LogLevel) -> LevelFilter { } } -pub fn init_logger(sender: Sender, log_file: &str) { +pub fn init_logger(sender: Sender<(LogType, String)>, log_file: &str) { simplelog::CombinedLogger::init(vec![ WriteLogger::new( translate_to_simple_logger(LogLevel::Trace), @@ -169,3 +201,34 @@ pub fn print_log(log_level: LogLevel, msg: String) { _ => {} }; } + +#[derive(Debug, Clone)] +pub struct MessageLogger { + sender: Sender<(LogType, String)>, +} + +impl MessageLogger { + pub fn new(sender: Sender<(LogType, String)>) -> Self { + Self { sender } + } + + pub fn print_log(&self, log_type: LogType, msg: String) { + let to_send = format!("{}\t{}", Local::now().format("%H:%M:%S"), msg); + self.sender.send((log_type.clone(), to_send)).unwrap(); + } +} + +pub fn init_msg_logger(sender: Sender<(LogType, String)>) { + let mut msg_logger = MSG_LOGGER.lock().unwrap(); + if msg_logger.is_none() { + // Initialize the variable + *msg_logger = Some(MessageLogger::new(sender)); + } +} + +pub fn pring_msg_logger(log_type: LogType, msg: String) { + let msg_logger = MSG_LOGGER.lock().unwrap(); + if let Some(logger) = msg_logger.as_ref() { + logger.print_log(log_type, msg); + } +} diff --git a/src/ui/logger.rs b/src/ui/logger.rs index b7c9ba9..a899a8c 100644 --- a/src/ui/logger.rs +++ b/src/ui/logger.rs @@ -7,6 +7,7 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::app::GPSApp; +use crate::logger; use crate::ui::treeview; use gtk::prelude::*; use gtk::{gio, glib}; @@ -18,18 +19,37 @@ fn reset_logger_list(logger_list: &TreeView) { String::static_type(), String::static_type(), String::static_type(), + String::static_type(), + String::static_type(), ]); logger_list.set_model(Some(&model)); } -pub fn setup_logger_list(app: &GPSApp) { - treeview::add_column_to_treeview(app, "treeview-logger", "TIME", 0, false); - treeview::add_column_to_treeview(app, "treeview-logger", "LEVEL", 1, false); - treeview::add_column_to_treeview(app, "treeview-logger", "LOG", 2, true); +pub fn setup_logger_list(app: &GPSApp, logger_name: &str, log_type: logger::LogType) { + match log_type { + logger::LogType::App => { + treeview::add_column_to_treeview(app, logger_name, "TIME", 0, false); + treeview::add_column_to_treeview(app, logger_name, "LEVEL", 1, false); + treeview::add_column_to_treeview(app, logger_name, "LOG", 2, true); + } + logger::LogType::Gst => { + treeview::add_column_to_treeview(app, logger_name, "TIME", 0, false); + treeview::add_column_to_treeview(app, logger_name, "LEVEL", 1, false); + treeview::add_column_to_treeview(app, logger_name, "CATEGORY", 2, false); + treeview::add_column_to_treeview(app, logger_name, "FILE", 3, false); + treeview::add_column_to_treeview(app, logger_name, "LOG", 4, true); + } + logger::LogType::Message => { + treeview::add_column_to_treeview(app, logger_name, "TIME", 0, false); + treeview::add_column_to_treeview(app, logger_name, "LEVEL", 1, false); + treeview::add_column_to_treeview(app, logger_name, "LOG", 2, true); + } + } + let logger_list: TreeView = app .builder - .object("treeview-logger") - .expect("Couldn't get treeview-logger"); + .object(logger_name) + .expect("Couldn't get treeview-app-logger"); reset_logger_list(&logger_list); let gesture = gtk::GestureClick::new(); @@ -59,17 +79,40 @@ pub fn setup_logger_list(app: &GPSApp) { logger_list.add_controller(gesture); } -pub fn add_to_logger_list(app: &GPSApp, log_entry: &str) { +fn log_tree_id_from_log_type(log_type: logger::LogType) -> String { + match log_type { + logger::LogType::App => String::from("treeview-app-logger"), + logger::LogType::Gst => String::from("treeview-gst-logger"), + logger::LogType::Message => String::from("treeview-msg-logger"), + } +} + +pub fn add_to_logger_list(app: &GPSApp, log_type: logger::LogType, log_entry: &str) { + let log_tree_name = log_tree_id_from_log_type(log_type.clone()); let logger_list: TreeView = app .builder - .object("treeview-logger") - .expect("Couldn't get treeview-logger"); + .object(log_tree_name.as_str()) + .expect("Couldn't get treeview"); if let Some(model) = logger_list.model() { let list_store = model .dynamic_cast::() .expect("Could not cast to ListStore"); - let log: Vec<&str> = log_entry.splitn(3, ' ').collect(); - list_store.insert_with_values(Some(0), &[(0, &log[0]), (1, &log[1]), (2, &log[2])]); + if log_type == logger::LogType::Gst { + let log: Vec<&str> = log_entry.splitn(5, '\t').collect(); + list_store.insert_with_values( + Some(0), + &[ + (0, &log[0]), + (1, &log[1]), + (2, &log[2]), + (3, &log[3]), + (4, &log[4]), + ], + ); + } else { + let log: Vec<&str> = log_entry.splitn(3, ' ').collect(); + list_store.insert_with_values(Some(0), &[(0, &log[0]), (1, &log[1]), (2, &log[2])]); + } // Scroll to the first element. if let Some(model) = logger_list.model() { if let Some(iter) = model.iter_first() {