use glib_sys;
use once_cell::sync::Lazy;
#[cfg(any(feature = "v2_46", feature = "dox"))]
use std::boxed::Box as Box_;
use std::sync::{Arc, Mutex};
use translate::*;
use GString;
#[derive(Debug)]
pub struct LogHandlerId(u32);
#[doc(hidden)]
impl FromGlib<u32> for LogHandlerId {
fn from_glib(value: u32) -> LogHandlerId {
LogHandlerId(value)
}
}
#[doc(hidden)]
impl ToGlib for LogHandlerId {
type GlibType = u32;
fn to_glib(&self) -> u32 {
self.0
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum LogLevel {
Error,
Critical,
Warning,
Message,
Info,
Debug,
}
#[doc(hidden)]
impl ToGlib for LogLevel {
type GlibType = u32;
fn to_glib(&self) -> u32 {
match *self {
LogLevel::Error => glib_sys::G_LOG_LEVEL_ERROR,
LogLevel::Critical => glib_sys::G_LOG_LEVEL_CRITICAL,
LogLevel::Warning => glib_sys::G_LOG_LEVEL_WARNING,
LogLevel::Message => glib_sys::G_LOG_LEVEL_MESSAGE,
LogLevel::Info => glib_sys::G_LOG_LEVEL_INFO,
LogLevel::Debug => glib_sys::G_LOG_LEVEL_DEBUG,
}
}
}
#[doc(hidden)]
impl FromGlib<u32> for LogLevel {
fn from_glib(value: u32) -> LogLevel {
if value & glib_sys::G_LOG_LEVEL_ERROR != 0 {
LogLevel::Error
} else if value & glib_sys::G_LOG_LEVEL_CRITICAL != 0 {
LogLevel::Critical
} else if value & glib_sys::G_LOG_LEVEL_WARNING != 0 {
LogLevel::Warning
} else if value & glib_sys::G_LOG_LEVEL_MESSAGE != 0 {
LogLevel::Message
} else if value & glib_sys::G_LOG_LEVEL_INFO != 0 {
LogLevel::Info
} else if value & glib_sys::G_LOG_LEVEL_DEBUG != 0 {
LogLevel::Debug
} else {
panic!("Unknown log level: {}", value)
}
}
}
bitflags! {
pub struct LogLevels: u32 {
const LEVEL_ERROR = glib_sys::G_LOG_LEVEL_ERROR;
const LEVEL_CRITICAL = glib_sys::G_LOG_LEVEL_CRITICAL;
const LEVEL_WARNING = glib_sys::G_LOG_LEVEL_WARNING;
const LEVEL_MESSAGE = glib_sys::G_LOG_LEVEL_MESSAGE;
const LEVEL_INFO = glib_sys::G_LOG_LEVEL_INFO;
const LEVEL_DEBUG = glib_sys::G_LOG_LEVEL_DEBUG;
}
}
#[doc(hidden)]
impl ToGlib for LogLevels {
type GlibType = glib_sys::GLogLevelFlags;
fn to_glib(&self) -> glib_sys::GLogLevelFlags {
self.bits()
}
}
#[doc(hidden)]
impl FromGlib<glib_sys::GLogLevelFlags> for LogLevels {
fn from_glib(value: glib_sys::GLogLevelFlags) -> LogLevels {
LogLevels::from_bits_truncate(value)
}
}
#[cfg(any(feature = "v2_46", feature = "dox"))]
fn to_log_flags(fatal: bool, recursion: bool) -> u32 {
(if fatal { glib_sys::G_LOG_FLAG_FATAL } else { 0 })
| if recursion {
glib_sys::G_LOG_FLAG_RECURSION
} else {
0
}
}
#[cfg(any(feature = "v2_46", feature = "dox"))]
pub fn log_set_handler<P: Fn(&str, LogLevel, &str) + Send + Sync + 'static>(
log_domain: Option<&str>,
log_levels: LogLevels,
fatal: bool,
recursion: bool,
log_func: P,
) -> LogHandlerId {
let log_func_data: Box_<P> = Box_::new(log_func);
unsafe extern "C" fn log_func_func<P: Fn(&str, LogLevel, &str) + Send + Sync + 'static>(
log_domain: *const libc::c_char,
log_level: glib_sys::GLogLevelFlags,
message: *const libc::c_char,
user_data: glib_sys::gpointer,
) {
let log_domain: Borrowed<GString> = from_glib_borrow(log_domain);
let message: Borrowed<GString> = from_glib_borrow(message);
let callback: &P = &*(user_data as *mut _);
(*callback)(log_domain.as_str(), from_glib(log_level), message.as_str());
}
let log_func = Some(log_func_func::<P> as _);
unsafe extern "C" fn destroy_func<P: Fn(&str, LogLevel, &str) + Send + Sync + 'static>(
data: glib_sys::gpointer,
) {
let _callback: Box_<P> = Box_::from_raw(data as *mut _);
}
let destroy_call4 = Some(destroy_func::<P> as _);
let super_callback0: Box_<P> = log_func_data;
unsafe {
from_glib(glib_sys::g_log_set_handler_full(
log_domain.to_glib_none().0,
log_levels.to_glib() | to_log_flags(fatal, recursion),
log_func,
Box_::into_raw(super_callback0) as *mut _,
destroy_call4,
))
}
}
pub fn log_remove_handler(log_domain: Option<&str>, handler_id: LogHandlerId) {
unsafe {
glib_sys::g_log_remove_handler(log_domain.to_glib_none().0, handler_id.to_glib());
}
}
pub fn log_set_always_fatal(fatal_levels: LogLevels) -> LogLevels {
unsafe { from_glib(glib_sys::g_log_set_always_fatal(fatal_levels.to_glib())) }
}
pub fn log_set_fatal_mask(log_domain: &str, fatal_levels: LogLevels) -> LogLevels {
unsafe {
from_glib(glib_sys::g_log_set_fatal_mask(
log_domain.to_glib_none().0,
fatal_levels.to_glib(),
))
}
}
type PrintCallback = dyn Fn(&str) + Send + Sync + 'static;
static PRINT_HANDLER: Lazy<Mutex<Option<Arc<PrintCallback>>>> = Lazy::new(|| Mutex::new(None));
pub fn set_print_handler<P: Fn(&str) + Send + Sync + 'static>(func: P) {
unsafe extern "C" fn func_func(string: *const libc::c_char) {
if let Some(callback) = match *PRINT_HANDLER.lock().expect("Failed to lock PRINT_HANDLER") {
Some(ref handler) => Some(Arc::clone(handler)),
None => None,
} {
let string: Borrowed<GString> = from_glib_borrow(string);
(*callback)(string.as_str())
}
}
*PRINT_HANDLER
.lock()
.expect("Failed to lock PRINT_HANDLER to change callback") = Some(Arc::new(func));
unsafe { glib_sys::g_set_print_handler(Some(func_func as _)) };
}
pub fn unset_print_handler() {
*PRINT_HANDLER
.lock()
.expect("Failed to lock PRINT_HANDLER to remove callback") = None;
unsafe { glib_sys::g_set_print_handler(None) };
}
static PRINTERR_HANDLER: Lazy<Mutex<Option<Arc<PrintCallback>>>> = Lazy::new(|| Mutex::new(None));
pub fn set_printerr_handler<P: Fn(&str) + Send + Sync + 'static>(func: P) {
unsafe extern "C" fn func_func(string: *const libc::c_char) {
if let Some(callback) = match *PRINTERR_HANDLER
.lock()
.expect("Failed to lock PRINTERR_HANDLER")
{
Some(ref handler) => Some(Arc::clone(handler)),
None => None,
} {
let string: Borrowed<GString> = from_glib_borrow(string);
(*callback)(string.as_str())
}
}
*PRINTERR_HANDLER
.lock()
.expect("Failed to lock PRINTERR_HANDLER to change callback") = Some(Arc::new(func));
unsafe { glib_sys::g_set_printerr_handler(Some(func_func as _)) };
}
pub fn unset_printerr_handler() {
*PRINTERR_HANDLER
.lock()
.expect("Failed to lock PRINTERR_HANDLER to remove callback") = None;
unsafe { glib_sys::g_set_printerr_handler(None) };
}
type LogCallback = dyn Fn(&str, LogLevel, &str) + Send + Sync + 'static;
static DEFAULT_HANDLER: Lazy<Mutex<Option<Arc<LogCallback>>>> = Lazy::new(|| Mutex::new(None));
pub fn log_set_default_handler<P: Fn(&str, LogLevel, &str) + Send + Sync + 'static>(log_func: P) {
unsafe extern "C" fn func_func(
log_domain: *const libc::c_char,
log_levels: glib_sys::GLogLevelFlags,
message: *const libc::c_char,
_user_data: glib_sys::gpointer,
) {
if let Some(callback) = match *DEFAULT_HANDLER
.lock()
.expect("Failed to lock DEFAULT_HANDLER")
{
Some(ref handler) => Some(Arc::clone(handler)),
None => None,
} {
let log_domain: Borrowed<GString> = from_glib_borrow(log_domain);
let message: Borrowed<GString> = from_glib_borrow(message);
(*callback)(log_domain.as_str(), from_glib(log_levels), message.as_str());
}
}
*DEFAULT_HANDLER
.lock()
.expect("Failed to lock DEFAULT_HANDLER to change callback") = Some(Arc::new(log_func));
unsafe { glib_sys::g_log_set_default_handler(Some(func_func as _), ::std::ptr::null_mut()) };
}
pub fn log_unset_default_handler() {
*DEFAULT_HANDLER
.lock()
.expect("Failed to lock DEFAULT_HANDLER to remove callback") = None;
unsafe {
glib_sys::g_log_set_default_handler(
Some(glib_sys::g_log_default_handler),
::std::ptr::null_mut(),
)
};
}
pub fn log_default_handler(log_domain: &str, log_level: LogLevel, message: Option<&str>) {
unsafe {
glib_sys::g_log_default_handler(
log_domain.to_glib_none().0,
log_level.to_glib(),
message.to_glib_none().0,
::std::ptr::null_mut(),
)
}
}
#[macro_export]
macro_rules! g_log {
($log_domain:expr, $log_level:expr, $format:expr, $($arg:expr),* $(,)?) => {{
use $crate::translate::{ToGlib, ToGlibPtr};
use $crate::LogLevel;
fn check_log_args(_log_domain: &str, _log_level: LogLevel, _format: &str) {}
check_log_args(&$log_domain, $log_level, $format);
let log_domain: &str = $log_domain;
let f = format!($format, $($arg),*).replace("%", "%%");
unsafe {
$crate::glib_sys::g_log(
log_domain.to_glib_none().0,
$log_level.to_glib(),
f.to_glib_none().0,
);
}
}};
($log_domain:expr, $log_level:expr, $format:expr $(,)?) => {{
use $crate::translate::{ToGlib, ToGlibPtr};
use $crate::LogLevel;
fn check_log_args(_log_domain: &str, _log_level: LogLevel, _format: &str) {}
check_log_args(&$log_domain, $log_level, $format);
let log_domain: &str = $log_domain;
let f = $format.replace("%", "%%");
unsafe {
$crate::glib_sys::g_log(
log_domain.to_glib_none().0,
$log_level.to_glib(),
f.to_glib_none().0,
);
}
}};
}
#[macro_export]
macro_rules! g_error {
($log_domain:expr, $format:expr, $($arg:expr),* $(,)?) => {{
$crate::g_log!($log_domain, $crate::LogLevel::Error, $format, $($arg),*);
}};
($log_domain:expr, $format:expr $(,)?) => {{
$crate::g_log!($log_domain, $crate::LogLevel::Error, $format);
}};
}
#[macro_export]
macro_rules! g_critical {
($log_domain:expr, $format:expr, $($arg:expr),* $(,)?) => {{
$crate::g_log!($log_domain, $crate::LogLevel::Critical, $format, $($arg),*);
}};
($log_domain:expr, $format:expr $(,)?) => {{
$crate::g_log!($log_domain, $crate::LogLevel::Critical, $format);
}};
}
#[macro_export]
macro_rules! g_warning {
($log_domain:expr, $format:expr, $($arg:expr),* $(,)?) => {{
$crate::g_log!($log_domain, $crate::LogLevel::Warning, $format, $($arg),*);
}};
($log_domain:expr, $format:expr $(,)?) => {{
$crate::g_log!($log_domain, $crate::LogLevel::Warning, $format);
}};
}
#[macro_export]
macro_rules! g_message {
($log_domain:expr, $format:expr, $($arg:expr),* $(,)?) => {{
$crate::g_log!($log_domain, $crate::LogLevel::Message, $format, $($arg),*);
}};
($log_domain:expr, $format:expr $(,)?) => {{
$crate::g_log!($log_domain, $crate::LogLevel::Message, $format);
}};
}
#[macro_export]
macro_rules! g_info {
($log_domain:expr, $format:expr, $($arg:expr),* $(,)?) => {{
$crate::g_log!($log_domain, $crate::LogLevel::Info, $format, $($arg),*);
}};
($log_domain:expr, $format:expr $(,)?) => {{
$crate::g_log!($log_domain, $crate::LogLevel::Info, $format);
}};
}
#[macro_export]
macro_rules! g_debug {
($log_domain:expr, $format:expr, $($arg:expr),* $(,)?) => {{
$crate::g_log!($log_domain, $crate::LogLevel::Debug, $format, $($arg),*);
}};
($log_domain:expr, $format:expr $(,)?) => {{
$crate::g_log!($log_domain, $crate::LogLevel::Debug, $format);
}};
}
#[doc(hidden)]
#[macro_export]
macro_rules! g_print_inner {
($func:ident, $format:expr) => {{
use $crate::translate::ToGlibPtr;
fn check_arg(_format: &str) {}
check_arg($format);
let f = $format.replace("%", "%%");
unsafe {
$crate::glib_sys::$func(f.to_glib_none().0);
}
}};
($func:ident, $format:expr, $($arg:expr),*) => {{
use $crate::translate::ToGlibPtr;
fn check_arg(_format: &str) {}
check_arg($format);
let f = format!($format, $($arg),*).replace("%", "%%");
unsafe {
$crate::glib_sys::$func(f.to_glib_none().0);
}
}};
}
#[macro_export]
macro_rules! g_print {
($format:expr, $($arg:expr),* $(,)?) => {{
$crate::g_print_inner!(g_print, $format, $($arg),*);
}};
($format:expr $(,)?) => {{
$crate::g_print_inner!(g_print, $format);
}};
}
#[macro_export]
macro_rules! g_printerr {
($format:expr $(,)?) => {{
$crate::g_print_inner!(g_printerr, $format);
}};
($format:expr, $($arg:expr),* $(,)?) => {{
$crate::g_print_inner!(g_printerr, $format, $($arg),*);
}};
}