1use std::ffi::{c_char, CStr};
7use std::sync::RwLock;
8use {ffi, Error, Result};
9
10#[derive(PartialEq, Eq, Clone, Debug, Copy, PartialOrd, Ord)]
12pub enum LogLevel {
13 Disabled,
15 Normal,
17 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#[no_mangle]
57pub unsafe extern "C" fn rust_write_formatted_msg(s: *const c_char) {
58 if s.is_null() {
59 return;
61 }
62 if let Ok(guard) = LOG_CALLBACK.read() {
63 if let Some(f) = *guard {
64 f(CStr::from_ptr(s));
65 }
66 }
68 }
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}