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
53/// # Safety
54///
55/// |s| must be null, or a pointer to a valid, nul-terminated, array of chars.
56#[no_mangle]
57pub unsafe extern "C" fn rust_write_formatted_msg(s: *const c_char) {
58    if s.is_null() {
59        // Do nothing if the pointer is null.
60        return;
61    }
62    if let Ok(guard) = LOG_CALLBACK.read() {
63        if let Some(f) = *guard {
64            f(CStr::from_ptr(s));
65        }
66        // Do nothing if there is no callback.
67    }
68    // Silently fail if lock cannot be acquired.
69}
70
71pub fn set_logging(level: LogLevel, f: Option<fn(s: &CStr)>) -> Result<()> {
72    match LOG_CALLBACK.write() {
73        Ok(mut guard) => {
74            *guard = f;
75        }
76        Err(_) => return Err(Error::error()),
77    }
78    unsafe {
79        call!(ffi::cubeb_set_log_callback(
80            level.into(),
81            Some(cubeb_write_log)
82        ))
83    }
84}
85
86#[cfg(test)]
87mod tests {
88    use super::*;
89
90    #[test]
91    fn test_logging_disabled_by_default() {
92        assert!(!log_enabled());
93    }
94}