From ca6c597fad86ac7de435fa31562074b0eaf14597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sat, 9 Sep 2017 14:12:49 +0300 Subject: [PATCH] Add bindings for the GStreamer logging system --- Gir_Gst.toml | 1 + gir-files/Gst-1.0.gir | 10 +- gstreamer/src/auto/flags.rs | 64 +++++++++ gstreamer/src/auto/mod.rs | 19 +++ gstreamer/src/lib.rs | 4 + gstreamer/src/log.rs | 260 ++++++++++++++++++++++++++++++++++++ 6 files changed, 353 insertions(+), 5 deletions(-) create mode 100644 gstreamer/src/log.rs diff --git a/Gir_Gst.toml b/Gir_Gst.toml index 4b7efce45..d66a89c13 100644 --- a/Gir_Gst.toml +++ b/Gir_Gst.toml @@ -71,6 +71,7 @@ generate = [ "Gst.Rank", "Gst.PadLinkCheck", "Gst.DebugLevel", + "Gst.DebugColorFlags", "Gst.StackTraceFlags", "Gst.DebugGraphDetails", "Gst.ParseFlags", diff --git a/gir-files/Gst-1.0.gir b/gir-files/Gst-1.0.gir index 42b5945c7..4e4213afb 100644 --- a/gir-files/Gst-1.0.gir +++ b/gir-files/Gst-1.0.gir @@ -10221,10 +10221,10 @@ debugging message. - + These are some terminal style flags you can use when creating your debugging categories to make them stand out in debugging output. glib:nick="underline"> Underline the output. - + ffi::GstDebugColorFlags { + ffi::GstDebugColorFlags::from_bits_truncate(self.bits()) + } +} + +#[doc(hidden)] +impl FromGlib for DebugColorFlags { + fn from_glib(value: ffi::GstDebugColorFlags) -> DebugColorFlags { + skip_assert_initialized!(); + DebugColorFlags::from_bits_truncate(value.bits()) + } +} + +impl StaticType for DebugColorFlags { + fn static_type() -> Type { + unsafe { from_glib(ffi::gst_debug_color_flags_get_type()) } + } +} + +impl<'a> FromValueOptional<'a> for DebugColorFlags { + unsafe fn from_value_optional(value: &Value) -> Option { + Some(FromValue::from_value(value)) + } +} + +impl<'a> FromValue<'a> for DebugColorFlags { + unsafe fn from_value(value: &Value) -> Self { + from_glib(ffi::GstDebugColorFlags::from_bits_truncate(gobject_ffi::g_value_get_flags(value.to_glib_none().0))) + } +} + +impl SetValue for DebugColorFlags { + unsafe fn set_value(value: &mut Value, this: &Self) { + gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, this.to_glib().bits()) + } +} + bitflags! { pub struct DebugGraphDetails: u32 { const DEBUG_GRAPH_SHOW_MEDIA_TYPE = 1; diff --git a/gstreamer/src/auto/mod.rs b/gstreamer/src/auto/mod.rs index 1f05c516d..7ee71f815 100644 --- a/gstreamer/src/auto/mod.rs +++ b/gstreamer/src/auto/mod.rs @@ -150,6 +150,25 @@ pub use self::flags::BUFFER_FLAG_DELTA_UNIT; pub use self::flags::BUFFER_FLAG_TAG_MEMORY; pub use self::flags::BUFFER_FLAG_SYNC_AFTER; pub use self::flags::BUFFER_FLAG_LAST; +pub use self::flags::DebugColorFlags; +pub use self::flags::DEBUG_FG_BLACK; +pub use self::flags::DEBUG_FG_RED; +pub use self::flags::DEBUG_FG_GREEN; +pub use self::flags::DEBUG_FG_YELLOW; +pub use self::flags::DEBUG_FG_BLUE; +pub use self::flags::DEBUG_FG_MAGENTA; +pub use self::flags::DEBUG_FG_CYAN; +pub use self::flags::DEBUG_FG_WHITE; +pub use self::flags::DEBUG_BG_BLACK; +pub use self::flags::DEBUG_BG_RED; +pub use self::flags::DEBUG_BG_GREEN; +pub use self::flags::DEBUG_BG_YELLOW; +pub use self::flags::DEBUG_BG_BLUE; +pub use self::flags::DEBUG_BG_MAGENTA; +pub use self::flags::DEBUG_BG_CYAN; +pub use self::flags::DEBUG_BG_WHITE; +pub use self::flags::DEBUG_BOLD; +pub use self::flags::DEBUG_UNDERLINE; pub use self::flags::DebugGraphDetails; pub use self::flags::DEBUG_GRAPH_SHOW_MEDIA_TYPE; pub use self::flags::DEBUG_GRAPH_SHOW_CAPS_DETAILS; diff --git a/gstreamer/src/lib.rs b/gstreamer/src/lib.rs index c0715a516..ab47ce624 100644 --- a/gstreamer/src/lib.rs +++ b/gstreamer/src/lib.rs @@ -56,6 +56,10 @@ mod auto; pub use auto::*; pub use auto::functions::*; +#[macro_use] +mod log; +pub use log::*; + pub mod miniobject; pub use miniobject::{GstRc, MiniObject}; pub mod message; diff --git a/gstreamer/src/log.rs b/gstreamer/src/log.rs new file mode 100644 index 000000000..500de0898 --- /dev/null +++ b/gstreamer/src/log.rs @@ -0,0 +1,260 @@ +// Copyright (C) 2016-2017 Sebastian Dröge +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use libc::c_char; +use std::ffi::CStr; +use std::fmt; +use std::ptr; +use std::mem; + +use gobject_ffi; +use ffi; + +use glib::IsA; +use glib::translate::{from_glib, ToGlib, ToGlibPtr}; + +#[derive(PartialEq, Eq, Clone, Copy)] +pub struct DebugCategory(*mut ffi::GstDebugCategory); + +impl DebugCategory { + pub fn new(name: &str, color: ::DebugColorFlags, description: &str) -> DebugCategory { + extern "C" { + fn _gst_debug_category_new( + name: *const c_char, + color: ffi::GstDebugColorFlags, + description: *const c_char, + ) -> *mut ffi::GstDebugCategory; + } + // Gets the category if it exists already + unsafe { + DebugCategory(_gst_debug_category_new( + name.to_glib_none().0, + color.to_glib(), + description.to_glib_none().0, + )) + } + } + + pub fn get(name: &str) -> Option { + unsafe { + extern "C" { + fn _gst_debug_get_category(name: *const c_char) -> *mut ffi::GstDebugCategory; + } + + let cat = _gst_debug_get_category(name.to_glib_none().0); + + if cat.is_null() { + None + } else { + Some(DebugCategory(cat)) + } + } + } + + pub fn get_threshold(&self) -> ::DebugLevel { + from_glib(unsafe { ffi::gst_debug_category_get_threshold(self.0) }) + } + + pub fn set_threshold(&self, threshold: ::DebugLevel) { + unsafe { ffi::gst_debug_category_set_threshold(self.0, threshold.to_glib()) } + } + + pub fn reset_threshold(&self) { + unsafe { ffi::gst_debug_category_reset_threshold(self.0) } + } + + pub fn get_color(&self) -> ::DebugColorFlags { + unsafe { + from_glib(mem::transmute::( + ffi::gst_debug_category_get_color(self.0), + )) + } + } + + pub fn get_name(&self) -> &str { + unsafe { + CStr::from_ptr(ffi::gst_debug_category_get_name(self.0)) + .to_str() + .unwrap() + } + } + + pub fn log>( + &self, + obj: Option<&O>, + level: ::DebugLevel, + file: &str, + module: &str, + line: u32, + args: fmt::Arguments, + ) { + if level.to_glib() as u32 > self.get_threshold().to_glib() as u32 { + return; + } + + let obj_ptr = match obj { + Some(obj) => obj.to_glib_none().0 as *mut gobject_ffi::GObject, + None => ptr::null_mut(), + }; + + unsafe { + ffi::gst_debug_log( + self.0, + level.to_glib(), + file.to_glib_none().0, + module.to_glib_none().0, + line as i32, + obj_ptr, + fmt::format(args).to_glib_none().0, + ); + } + } +} + +unsafe impl Sync for DebugCategory {} +unsafe impl Send for DebugCategory {} + +impl fmt::Debug for DebugCategory { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(self.get_name()) + } +} + +#[macro_export] +macro_rules! gst_error( + ($cat:expr, obj: $obj:expr, $($args:tt)*) => { { + gst_log_with_level!($cat, level: $crate::DebugLevel::Error, obj: $obj, $($args)*) + }}; + ($cat:expr, $($args:tt)*) => { { + gst_log_with_level!($cat, level: $crate::DebugLevel::Error, $($args)*) + }}; +); + +#[macro_export] +macro_rules! gst_warning( + ($cat:expr, obj: $obj:expr, $($args:tt)*) => { { + gst_log_with_level!($cat, level: $crate::DebugLevel::Warning, obj: $obj, $($args)*) + }}; + ($cat:expr, $($args:tt)*) => { { + gst_log_with_level!($cat, level: $crate::DebugLevel::Warning, $($args)*) + }}; +); + +#[macro_export] +macro_rules! gst_fixme( + ($cat:expr, obj: $obj:expr, $($args:tt)*) => { { + gst_log_with_level!($cat, level: $crate::DebugLevel::Fixme, obj: $obj, $($args)*) + }}; + ($cat:expr, $($args:tt)*) => { { + gst_log_with_level!($cat, level: $crate::DebugLevel::Fixme, $($args)*) + }}; +); + +#[macro_export] +macro_rules! gst_info( + ($cat:expr, obj: $obj:expr, $($args:tt)*) => { { + gst_log_with_level!($cat, level: $crate::DebugLevel::Info, obj: $obj, $($args)*) + }}; + ($cat:expr, $($args:tt)*) => { { + gst_log_with_level!($cat, level: $crate::DebugLevel::Info, $($args)*) + }}; +); + +#[macro_export] +macro_rules! gst_debug( + ($cat:expr, obj: $obj:expr, $($args:tt)*) => { { + gst_log_with_level!($cat, level: $crate::DebugLevel::Debug, obj: $obj, $($args)*) + }}; + ($cat:expr, $($args:tt)*) => { { + gst_log_with_level!($cat, level: $crate::DebugLevel::Debug, $($args)*) + }}; +); + +#[macro_export] +macro_rules! gst_log( + ($cat:expr, obj: $obj:expr, $($args:tt)*) => { { + gst_log_with_level!($cat, level: $crate::DebugLevel::Log, obj: $obj, $($args)*) + }}; + ($cat:expr, $($args:tt)*) => { { + gst_log_with_level!($cat, level: $crate::DebugLevel::Log, $($args)*) + }}; +); + +#[macro_export] +macro_rules! gst_trace( + ($cat:expr, obj: $obj:expr, $($args:tt)*) => { { + gst_log_with_level!($cat, level: $crate::DebugLevel::Trace, obj: $obj, $($args)*) + }}; + ($cat:expr, $($args:tt)*) => { { + gst_log_with_level!($cat, level: $crate::DebugLevel::Trace, $($args)*) + }}; +); + +#[macro_export] +macro_rules! gst_memdump( + ($cat:expr, obj: $obj:expr, $($args:tt)*) => { { + gst_log_with_level!($cat, level: $crate::DebugLevel::Memdump, obj: $obj, $($args)*) + }}; + ($cat:expr, $($args:tt)*) => { { + gst_log_with_level!($cat, level: $crate::DebugLevel::Memdump, $($args)*) + }}; +); + +#[macro_export] +macro_rules! gst_log_with_level( + ($cat:expr, level: $level:expr, obj: $obj:expr, $($args:tt)*) => { { + $crate::DebugCategory::log(&$cat, Some(&$obj), $level, file!(), + module_path!(), line!(), format_args!($($args)*)) + }}; + ($cat:expr, level: $level:expr, $($args:tt)*) => { { + $crate::DebugCategory::log(&$cat, None as Option<&$crate::Object>, $level, file!(), + module_path!(), line!(), format_args!($($args)*)) + }}; +); + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn get_existing() { + ::init().unwrap(); + + assert_ne!(DebugCategory::get("GST_PERFORMANCE"), None); + } + + #[test] + fn new_and_log() { + ::init().unwrap(); + + let cat = DebugCategory::new( + "test-cat", + ::DebugColorFlags::empty(), + "some debug category", + ); + + gst_error!(cat, "meh"); + gst_warning!(cat, "meh"); + gst_fixme!(cat, "meh"); + gst_info!(cat, "meh"); + gst_debug!(cat, "meh"); + gst_log!(cat, "meh"); + gst_trace!(cat, "meh"); + gst_memdump!(cat, "meh"); + + let obj = ::Bin::new("meh"); + gst_error!(cat, obj: obj, "meh"); + gst_warning!(cat, obj: obj, "meh"); + gst_fixme!(cat, obj: obj, "meh"); + gst_info!(cat, obj: obj, "meh"); + gst_debug!(cat, obj: obj, "meh"); + gst_log!(cat, obj: obj, "meh"); + gst_trace!(cat, obj: obj, "meh"); + gst_memdump!(cat, obj: obj, "meh"); + } +}