cubeb_core/
log.rs

1// Copyright © 2017-2018 Mozilla Foundation
2//
3// This program is made available under an ISC-style license.  See the
4// accompanying file LICENSE for details.
5
6use std::ffi::{c_char, CStr};
7use std::sync::RwLock;
8use {ffi, Error, Result};
9
10/// Level (verbosity) of logging for a particular cubeb context.
11#[derive(PartialEq, Eq, Clone, Debug, Copy, PartialOrd, Ord)]
12pub enum LogLevel {
13    /// Logging disabled
14    Disabled,
15    /// Logging lifetime operation (creation/destruction).
16    Normal,
17    /// Verbose logging of callbacks, can have performance implications.
18    Verbose,
19}
20
21impl From<ffi::cubeb_log_level> for LogLevel {
22    fn from(x: ffi::cubeb_log_level) -> Self {
23        use LogLevel::*;
24        match x {
25            ffi::CUBEB_LOG_NORMAL => Normal,
26            ffi::CUBEB_LOG_VERBOSE => Verbose,
27            _ => Disabled,
28        }
29    }
30}
31
32impl From<LogLevel> for ffi::cubeb_log_level {
33    fn from(x: LogLevel) -> Self {
34        use LogLevel::*;
35        match x {
36            Normal => ffi::CUBEB_LOG_NORMAL,
37            Verbose => ffi::CUBEB_LOG_VERBOSE,
38            Disabled => ffi::CUBEB_LOG_DISABLED,
39        }
40    }
41}
42
43pub fn log_enabled() -> bool {
44    unsafe { ffi::cubeb_log_get_level() != LogLevel::Disabled as _ }
45}
46
47static LOG_CALLBACK: RwLock<Option<fn(s: &CStr)>> = RwLock::new(None);
48
49extern "C" {
50    fn cubeb_write_log(fmt: *const c_char, ...);
51}
52
53include!(concat!(env!("OUT_DIR"), "/log_wrap.rs"));
54
55/// # Safety
56///
57/// |s| must be null, or a pointer to a valid, nul-terminated, array of chars.
58pub unsafe fn rust_write_formatted_msg(s: *const c_char) {
59    if s.is_null() {
60        // Do nothing if the pointer is null.
61        return;
62    }
63    if let Ok(guard) = LOG_CALLBACK.read() {
64        if let Some(f) = *guard {
65            f(CStr::from_ptr(s));
66        }
67        // Do nothing if there is no callback.
68    }
69    // Silently fail if lock cannot be acquired.
70}
71
72pub fn set_logging(level: LogLevel, f: Option<fn(s: &CStr)>) -> Result<()> {
73    match LOG_CALLBACK.write() {
74        Ok(mut guard) => {
75            *guard = f;
76        }
77        Err(_) => return Err(Error::Error),
78    }
79    unsafe {
80        call!(ffi::cubeb_set_log_callback(
81            level.into(),
82            if level == LogLevel::Disabled {
83                None
84            } else {
85                Some(cubeb_write_log)
86            }
87        ))
88    }
89}
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94
95    #[test]
96    fn test_logging_disabled_by_default() {
97        assert!(!log_enabled());
98    }
99}