Compare commits

...

7 commits

Author SHA1 Message Date
Nick Steel 85d995af7c Merge branch 'log-trait-adapter' into 'main'
log: `Log` trait adapter around the GStreamer debug system

Closes #187

See merge request gstreamer/gstreamer-rs!1426
2024-04-27 16:24:54 +00:00
Sebastian Dröge 241338f43c audio: video: Improve Display trait impl test for AudioFormat and Video a bit
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1432>
2024-04-27 16:10:49 +00:00
Sebastian Dröge 5c8a989029 video: Remove nonsensical test
Printing an unknown video format returns NULL, and with latest git main
this actually causes a critical warning in addition.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1432>
2024-04-27 16:10:49 +00:00
Nick Steel a77022ba0e log: check category above threshold 2024-04-22 01:05:38 +01:00
Nick Steel 8dd9a2d5ee log: DebugCategoryLogger is optional via 'log' feature 2024-04-21 22:23:36 +01:00
Sebastian Dröge 1438fa88db Apply 1 suggestion(s) to 1 file(s) 2024-04-21 09:22:32 +00:00
Nick Steel 08169aca96 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
2024-04-21 00:12:31 +01:00
5 changed files with 117 additions and 9 deletions

View file

@ -364,7 +364,8 @@ mod tests {
fn test_display() {
gst::init().unwrap();
format!("{}", crate::AudioFormat::S16be);
assert_eq!(format!("{}", crate::AudioFormat::S16be), "S16BE");
assert_eq!(format!("{:?}", crate::AudioFormat::S16be), "S16be");
}
#[test]

View file

@ -480,18 +480,12 @@ mod tests {
);
}
#[test]
#[should_panic(expected = "gst_video_format_to_string returned NULL")]
fn enum_to_string_panics() {
assert_eq!(&format!("{}", crate::VideoFormat::__Unknown(-1)), "UNKNOWN");
assert_eq!(crate::VideoFormat::__Unknown(-1).to_str(), "UNKNOWN");
}
#[test]
fn test_display() {
gst::init().unwrap();
format!("{}", crate::VideoFormat::Nv16);
assert_eq!(format!("{}", crate::VideoFormat::Nv16), "NV16");
assert_eq!(format!("{:?}", crate::VideoFormat::Nv16), "Nv16");
}
#[test]

View file

@ -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 = { version = "0.4", optional = true }
muldiv = "1"
opt-ops = { package = "option-operations", version = "0.5" }
serde = { version = "1.0", optional = true, features = ["derive"] }
@ -48,6 +49,7 @@ v1_20 = ["ffi/v1_20", "v1_18"]
v1_22 = ["ffi/v1_22", "v1_20"]
v1_24 = ["ffi/v1_24", "v1_22"]
serde = ["num-rational/serde", "dep:serde", "serde_bytes"]
log = ["dep:log"]
[package.metadata.docs.rs]
all-features = true

View file

@ -49,6 +49,8 @@ mod serde_macros;
#[macro_use]
pub mod log;
#[cfg(feature = "log")]
pub use crate::log::DebugCategoryLogger;
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,

View file

@ -4,6 +4,8 @@ use std::{borrow::Cow, ffi::CStr, fmt, ptr};
use glib::{ffi::gpointer, prelude::*, translate::*};
use libc::c_char;
#[cfg(feature = "log")]
use log;
use once_cell::sync::Lazy;
use crate::DebugLevel;
@ -1064,6 +1066,54 @@ macro_rules! log_with_level(
}};
);
#[cfg(feature = "log")]
#[derive(Debug)]
pub struct DebugCategoryLogger(DebugCategory);
#[cfg(feature = "log")]
impl DebugCategoryLogger {
pub fn new(cat: DebugCategory) -> Self {
Self(cat)
}
fn to_level(level: log::Level) -> crate::DebugLevel {
match 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,
}
}
}
#[cfg(feature = "log")]
impl log::Log for DebugCategoryLogger {
fn enabled(&self, metadata: &log::Metadata) -> bool {
let lvl = DebugCategoryLogger::to_level(metadata.level());
is_active() && self.0.above_threshold(lvl)
}
fn log(&self, record: &log::Record) {
if !self.enabled(record.metadata()) {
return;
}
let lvl = DebugCategoryLogger::to_level(record.level());
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<T>(
category: *mut ffi::GstDebugCategory,
level: ffi::GstDebugLevel,
@ -1308,6 +1358,65 @@ mod tests {
memdump!(cat, obj: obj, "meh");
}
#[cfg(feature = "log")]
static LOGGER: Lazy<DebugCategoryLogger> = Lazy::new(|| {
DebugCategoryLogger::new(DebugCategory::new(
"Log_trait",
crate::DebugColorFlags::empty(),
Some("Using the Log trait"),
))
});
#[test]
#[cfg(feature = "log")]
fn log_trait() {
crate::init().unwrap();
log::set_logger(&(*LOGGER)).expect("Failed to set logger");
log::set_max_level(log::LevelFilter::Trace);
log::error!("meh");
log::warn!("fish");
let (sender, receiver) = mpsc::channel();
let sender = Arc::new(Mutex::new(sender));
let handler = move |category: DebugCategory,
level: DebugLevel,
_file: &glib::GStr,
_function: &glib::GStr,
_line: u32,
_object: Option<&LoggedObject>,
message: &DebugMessage| {
let cat = DebugCategory::get("Log_trait").unwrap();
if category != cat {
// This test can run in parallel with other tests, including new_and_log above.
// We cannot be certain we only see our own messages.
return;
}
assert_eq!(level, DebugLevel::Error);
assert_eq!(message.get().unwrap().as_ref(), "meh");
let _ = sender.lock().unwrap().send(());
};
remove_default_log_function();
add_log_function(handler);
let cat = LOGGER.0;
cat.set_threshold(crate::DebugLevel::Warning);
log::error!("meh");
receiver.recv().unwrap();
cat.set_threshold(crate::DebugLevel::Error);
log::error!("meh");
receiver.recv().unwrap();
cat.set_threshold(crate::DebugLevel::None);
log::error!("fish");
log::warn!("meh");
}
#[test]
fn log_handler() {
crate::init().unwrap();