diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 1b2c027..1186c08 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -9,7 +9,7 @@ gio = "0.9.1" glib = "0.10.3" gstreamer = "0.16.4" gstreamer-player = "0.16.3" -log = "0.4.14" +log = { version = "0.4.14", features = ["std"] } musicus_client = { version = "0.1.0", path = "../client" } musicus_database = { version = "0.1.0", path = "../database" } musicus_import = { version = "0.1.0", path = "../import" } diff --git a/backend/src/lib.rs b/backend/src/lib.rs index 92282b3..1f1797f 100644 --- a/backend/src/lib.rs +++ b/backend/src/lib.rs @@ -20,6 +20,8 @@ pub use error::*; pub mod library; pub use library::*; +mod logger; + pub mod player; pub use player::*; @@ -70,8 +72,11 @@ pub struct Backend { impl Backend { /// Create a new backend initerface. The user interface should subscribe to the state stream - /// and call init() afterwards. + /// and call init() afterwards. There may be only one backend for a process and this method + /// may only be called exactly once. Otherwise it will panic. pub fn new() -> Self { + logger::register(); + let (state_sender, _) = broadcast::channel(1024); let (library_updated_sender, _) = broadcast::channel(1024); diff --git a/backend/src/logger.rs b/backend/src/logger.rs new file mode 100644 index 0000000..731caa3 --- /dev/null +++ b/backend/src/logger.rs @@ -0,0 +1,63 @@ +use log::{Level, LevelFilter, Log, Metadata, Record}; +use std::{fmt::Display, sync::Mutex}; + +/// Register the custom logger. This will panic if called more than once. +pub fn register() { + log::set_boxed_logger(Box::new(Logger::default())) + .map(|()| log::set_max_level(LevelFilter::Info)) + .unwrap(); +} + +/// A simple logging handler that prints out all messages and caches them for +/// later access by the user interface. +struct Logger { + /// All messages since the start of the program. + messages: Mutex>, +} + +impl Default for Logger { + fn default() -> Self { + Self { + messages: Mutex::new(Vec::new()), + } + } +} + +impl Log for Logger { + fn enabled(&self, metadata: &Metadata) -> bool { + metadata.level() <= Level::Info + } + + fn log(&self, record: &Record) { + if record.level() <= Level::Info { + let message = record.into(); + println!("{}", message); + self.messages.lock().unwrap().push(message); + } + } + + fn flush(&self) {} +} + +/// A simplified representation of a [`Record`]. +struct LogMessage { + pub level: String, + pub module: String, + pub message: String, +} + +impl<'a> From<&Record<'a>> for LogMessage { + fn from(record: &Record<'a>) -> Self { + Self { + level: record.level().to_string(), + module: String::from(record.module_path().unwrap_or_else(|| record.target())), + message: format!("{}", record.args()), + } + } +} + +impl Display for LogMessage { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{} ({}): {}", self.module, self.level, self.message) + } +} diff --git a/musicus/Cargo.toml b/musicus/Cargo.toml index 0c2bae8..36aaaff 100644 --- a/musicus/Cargo.toml +++ b/musicus/Cargo.toml @@ -6,7 +6,6 @@ edition = "2018" [dependencies] anyhow = "1.0.33" async-trait = "0.1.42" -env_logger = "0.8.3" futures-channel = "0.3.5" gettext-rs = { version = "0.5.0", features = ["gettext-system"] } gstreamer = "0.16.4" diff --git a/musicus/src/main.rs b/musicus/src/main.rs index 0d069df..a851c7d 100644 --- a/musicus/src/main.rs +++ b/musicus/src/main.rs @@ -25,8 +25,6 @@ fn main() { gettextrs::bindtextdomain("musicus", config::LOCALEDIR); gettextrs::textdomain("musicus"); - env_logger::init(); - gstreamer::init().expect("Failed to initialize GStreamer!"); gtk::init().expect("Failed to initialize GTK!"); libadwaita::init();