Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow clients to set a log callback. #98

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}

54 changes: 53 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,60 @@ 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.
#[no_mangle]
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
Loading