1use std::{
19 ffi::{CStr, c_char},
20 sync::Once,
21};
22
23use libcdio_sys::{
24 cdio_log_level_t, cdio_log_level_t_CDIO_LOG_ASSERT, cdio_log_level_t_CDIO_LOG_DEBUG,
25 cdio_log_level_t_CDIO_LOG_ERROR, cdio_log_level_t_CDIO_LOG_INFO,
26 cdio_log_level_t_CDIO_LOG_WARN,
27};
28
29pub(crate) fn init_logger() {
32 LOG_HANDLER.call_once(|| unsafe {
33 libcdio_sys::cdio_log_set_handler(Some(log_handler));
34
35 libcdio_sys::cdio_loglevel_default = cdio_log_level_t_CDIO_LOG_DEBUG;
39 });
40}
41
42static LOG_HANDLER: Once = Once::new();
43
44extern "C" fn log_handler(level: cdio_log_level_t, message: *const c_char) {
46 if message.is_null() {
47 return;
48 }
49 let message = unsafe { CStr::from_ptr(message) };
52 let Ok(message) = message.to_str() else {
53 return;
54 };
55 #[allow(non_upper_case_globals)]
56 match level {
57 cdio_log_level_t_CDIO_LOG_ASSERT | cdio_log_level_t_CDIO_LOG_ERROR => {
58 tracing::error!(message)
59 }
60 cdio_log_level_t_CDIO_LOG_WARN => tracing::warn!(message),
61 cdio_log_level_t_CDIO_LOG_INFO => tracing::info!(message),
62 _ => tracing::debug!(message),
63 };
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test_log::test(test)]
71 fn log_test() {
72 init_logger();
73 unsafe {
74 libcdio_sys::cdio_log(cdio_log_level_t_CDIO_LOG_ASSERT, c"assert msg".as_ptr());
75 libcdio_sys::cdio_log(cdio_log_level_t_CDIO_LOG_ERROR, c"error msg".as_ptr());
76 libcdio_sys::cdio_log(cdio_log_level_t_CDIO_LOG_WARN, c"warn msg".as_ptr());
77 libcdio_sys::cdio_log(cdio_log_level_t_CDIO_LOG_INFO, c"info msg".as_ptr());
78 libcdio_sys::cdio_log(cdio_log_level_t_CDIO_LOG_DEBUG, c"debug msg".as_ptr());
79 }
80 }
81}