Skip to content

Commit

Permalink
Allow clients to set a log callback.
Browse files Browse the repository at this point in the history
  • Loading branch information
mutexlox-signal committed Oct 17, 2024
1 parent 716a8b4 commit bfed05d
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 1 deletion.
3 changes: 3 additions & 0 deletions cubeb-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@ gecko-in-tree = ["cubeb-sys/gecko-in-tree"]
[dependencies]
bitflags = "1.2.0"
cubeb-sys = { path = "../cubeb-sys", version = "0.14" }

[build-dependencies]
cc = "1.1.30"
3 changes: 3 additions & 0 deletions cubeb-core/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
cc::Build::new().file("src/log.c").compile("cubeb_log_wrap");
}
17 changes: 17 additions & 0 deletions cubeb-core/src/log.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include <stdarg.h>
#include <stdio.h>

/** The maximum size of a log message, after having been formatted. */
#define CUBEB_LOG_MESSAGE_MAX_SIZE 256

void rust_write_formatted_msg(char* msg);

void cubeb_write_log(char const * fmt, ...) {
va_list args;
va_start(args, fmt);
char msg[CUBEB_LOG_MESSAGE_MAX_SIZE];
vsnprintf(msg, CUBEB_LOG_MESSAGE_MAX_SIZE, fmt, args);
va_end(args);
rust_write_formatted_msg(msg);
}

53 changes: 52 additions & 1 deletion cubeb-core/src/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
// This program is made available under an ISC-style license. See the
// accompanying file LICENSE for details.

use ffi;
use std::ffi::{c_char, CStr};
use std::sync::Mutex;
use {ffi, Error, Result};

/// Level (verbosity) of logging for a particular cubeb context.
#[derive(PartialEq, Eq, Clone, Debug, Copy, PartialOrd, Ord)]
Expand All @@ -27,10 +29,59 @@ impl From<ffi::cubeb_log_level> for LogLevel {
}
}

impl From<LogLevel> for ffi::cubeb_log_level {
fn from(x: LogLevel) -> Self {
use LogLevel::*;
match x {
Normal => ffi::CUBEB_LOG_NORMAL,
Verbose => ffi::CUBEB_LOG_VERBOSE,
Disabled => ffi::CUBEB_LOG_DISABLED,
}
}
}

pub fn log_enabled() -> bool {
unsafe { ffi::cubeb_log_get_level() != LogLevel::Disabled as _ }
}

static LOG_CALLBACK: Mutex<Option<fn(s: &CStr)>> = Mutex::new(None);

extern "C" {
fn cubeb_write_log(fmt: *const c_char, ...);
}

/// # Safety
///
/// |s| must be null, or a pointer to a valid, nul-terminated, array of chars.
pub unsafe extern "C" fn rust_write_formatted_msg(s: *const c_char) {
if s.is_null() {
// Do nothing if the pointer is null.
return;
}
if let Ok(guard) = LOG_CALLBACK.lock() {
if let Some(f) = *guard {
f(CStr::from_ptr(s));
}
// Do nothing if there is no callback.
}
// Silently fail if lock cannot be acquired.
}

pub fn set_logging(level: LogLevel, f: Option<fn(s: &CStr)>) -> Result<()> {
match LOG_CALLBACK.lock() {
Ok(mut guard) => {
*guard = f;
}
Err(_) => return Err(Error::error()),
}
unsafe {
call!(ffi::cubeb_set_log_callback(
level.into(),
Some(cubeb_write_log)
))
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down

0 comments on commit bfed05d

Please sign in to comment.