libobs_wrapper\logger/
mod.rs

1//! This module is used to provide a logger trait, which can be used to implement custom logging
2//! for the libobs console output.
3
4mod console;
5mod file;
6pub use console::ConsoleLogger;
7pub use file::FileLogger;
8
9use std::{fmt::Debug, os::raw::c_void, sync::Mutex};
10
11use lazy_static::lazy_static;
12use num_traits::FromPrimitive;
13use vsprintf::vsprintf;
14
15use crate::enums::ObsLogLevel;
16
17lazy_static! {
18    /// We are using this as global variable because there can only be one obs context
19    pub(crate) static ref LOGGER: Mutex<Box<dyn ObsLogger>> = Mutex::new(Box::new(ConsoleLogger::new()));
20}
21
22/// # Safety
23/// This function is unsafe because it is called from C code.
24pub(crate) unsafe extern "C" fn extern_log_callback<V>(
25    log_level: i32,
26    msg: *const i8,
27    args: *mut V,
28    _params: *mut c_void,
29) {
30    let level = ObsLogLevel::from_i32(log_level);
31    if level.is_none() {
32        eprintln!("Couldn't find log level {}", log_level);
33        return;
34    }
35
36    let level = level.unwrap();
37
38    let formatted = vsprintf(msg, args);
39    if formatted.is_err() {
40        eprintln!("Failed to format log message");
41        return;
42    }
43
44    let mut logger = LOGGER.lock().unwrap();
45
46    logger.log(level, formatted.unwrap());
47}
48
49pub trait ObsLogger
50where
51    Self: Send + Debug,
52{
53    fn log(&mut self, level: ObsLogLevel, msg: String);
54}
55
56pub(crate) fn internal_log_global(level: ObsLogLevel, msg: String) {
57    let mut logger = LOGGER.lock().unwrap();
58    logger.log(level, msg);
59}