From 78d4db1b6cfe722d76fb5d2bf79527ed0b722baa Mon Sep 17 00:00:00 2001 From: Nick Steel Date: Sun, 21 Apr 2024 00:12:31 +0100 Subject: [PATCH] log: `Log` trait adapter around the GStreamer debug system Allows usage of normal `log` crate macros, and for other crates using those macros to have their log messages go to the GStreamer debug logs. This implementation is based on the one found in Servo. Fixes #187 --- gstreamer/Cargo.toml | 1 + gstreamer/src/lib.rs | 12 +++++----- gstreamer/src/log.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 6 deletions(-) diff --git a/gstreamer/Cargo.toml b/gstreamer/Cargo.toml index d6e20807b..7324a7566 100644 --- a/gstreamer/Cargo.toml +++ b/gstreamer/Cargo.toml @@ -23,6 +23,7 @@ num-rational = { version = "0.4", default-features = false, features = [] } futures-core = "0.3" futures-channel = "0.3" futures-util = { version = "0.3", default-features = false } +log = "0.4" muldiv = "1" opt-ops = { package = "option-operations", version = "0.5" } serde = { version = "1.0", optional = true, features = ["derive"] } diff --git a/gstreamer/src/lib.rs b/gstreamer/src/lib.rs index 2d65fa6ad..71b499e27 100644 --- a/gstreamer/src/lib.rs +++ b/gstreamer/src/lib.rs @@ -50,12 +50,12 @@ mod serde_macros; #[macro_use] pub mod log; pub use crate::log::{ - DebugCategory, DebugLogFunction, DebugMessage, LoggedObject, CAT_BUFFER, CAT_BUFFER_LIST, - CAT_BUS, CAT_CALL_TRACE, CAT_CAPS, CAT_CLOCK, CAT_CONTEXT, CAT_DEFAULT, CAT_ELEMENT_PADS, - CAT_ERROR_SYSTEM, CAT_EVENT, CAT_GST_INIT, CAT_LOCKING, CAT_MEMORY, CAT_MESSAGE, CAT_META, - CAT_NEGOTIATION, CAT_PADS, CAT_PARAMS, CAT_PARENTAGE, CAT_PERFORMANCE, CAT_PIPELINE, - CAT_PLUGIN_INFO, CAT_PLUGIN_LOADING, CAT_PROBE, CAT_PROPERTIES, CAT_QOS, CAT_REFCOUNTING, - CAT_REGISTRY, CAT_RUST, CAT_SCHEDULING, CAT_SIGNAL, CAT_STATES, + DebugCategory, DebugCategoryLogger, DebugLogFunction, DebugMessage, LoggedObject, CAT_BUFFER, + CAT_BUFFER_LIST, CAT_BUS, CAT_CALL_TRACE, CAT_CAPS, CAT_CLOCK, CAT_CONTEXT, CAT_DEFAULT, + CAT_ELEMENT_PADS, CAT_ERROR_SYSTEM, CAT_EVENT, CAT_GST_INIT, CAT_LOCKING, CAT_MEMORY, + CAT_MESSAGE, CAT_META, CAT_NEGOTIATION, CAT_PADS, CAT_PARAMS, CAT_PARENTAGE, CAT_PERFORMANCE, + CAT_PIPELINE, CAT_PLUGIN_INFO, CAT_PLUGIN_LOADING, CAT_PROBE, CAT_PROPERTIES, CAT_QOS, + CAT_REFCOUNTING, CAT_REGISTRY, CAT_RUST, CAT_SCHEDULING, CAT_SIGNAL, CAT_STATES, }; #[cfg(target_os = "macos")] diff --git a/gstreamer/src/log.rs b/gstreamer/src/log.rs index 8c90f5d8d..c3c1b7441 100644 --- a/gstreamer/src/log.rs +++ b/gstreamer/src/log.rs @@ -4,6 +4,7 @@ use std::{borrow::Cow, ffi::CStr, fmt, ptr}; use glib::{ffi::gpointer, prelude::*, translate::*}; use libc::c_char; +use log; use once_cell::sync::Lazy; use crate::DebugLevel; @@ -1064,6 +1065,43 @@ macro_rules! log_with_level( }}; ); +#[derive(Debug)] +pub struct DebugCategoryLogger(DebugCategory); + +impl DebugCategoryLogger { + pub fn new(cat: DebugCategory) -> Self { + Self(cat) + } +} + +impl log::Log for DebugCategoryLogger { + fn enabled(&self, _metadata: &log::Metadata) -> bool { + true + } + + fn log(&self, record: &log::Record) { + let lvl = match record.level() { + log::Level::Error => DebugLevel::Error, + log::Level::Warn => DebugLevel::Warning, + log::Level::Info => DebugLevel::Info, + log::Level::Debug => DebugLevel::Debug, + log::Level::Trace => DebugLevel::Trace, + }; + let file = record.file().unwrap_or(""); + let file = glib::GStr::from_str_until_nul(file).unwrap_or_default(); + self.0.log( + None::<&glib::Object>, + lvl, + file, + record.module_path().unwrap_or(""), + record.line().unwrap_or(0), + record.args().clone(), + ); + } + + fn flush(&self) {} +} + unsafe extern "C" fn log_handler( category: *mut ffi::GstDebugCategory, level: ffi::GstDebugLevel, @@ -1308,6 +1346,22 @@ mod tests { memdump!(cat, obj: obj, "meh"); } + static LOGGER: Lazy = Lazy::new(|| { + DebugCategoryLogger::new(DebugCategory::new( + "Log_trait", + crate::DebugColorFlags::empty(), + Some("Using the Log trait"), + )) + }); + + #[test] + fn log_trait() { + crate::init().unwrap(); + + log::set_logger(&(*LOGGER)).expect("Failed to set logger"); + log::error!("meh"); + } + #[test] fn log_handler() { crate::init().unwrap();