diff --git a/src/bin/cmus-notify.rs b/src/bin/cmus-notify.rs index f525bbb..89e7aa0 100644 --- a/src/bin/cmus-notify.rs +++ b/src/bin/cmus-notify.rs @@ -1,6 +1,6 @@ use cmus_notify::{ cmus::{self, events::CmusEvent, query::CmusQueryResponse}, - notification, + notification, settings, settings::Settings, track_cover, TrackCover, }; @@ -38,19 +38,15 @@ fn main() { } // Build the command, or use the default. (to speed up the main loop, because we don't need to build it every time) - let remote_bin_path = settings - .cmus_remote_bin_path - .clone() - .unwrap_or("cmus-remote".to_string()); let mut query_command = cmus::build_query_command( - remote_bin_path.as_str(), + settings.remote_bin_path().as_str(), &settings.cmus_socket_address, &settings.cmus_socket_password, ); #[cfg(feature = "debug")] info!("Query command built: {:?}", query_command); - let interval = settings.interval; + let interval = settings.interval(); let link = settings.link; let mut notifications_handler = notification::NotificationsHandler::new(settings); diff --git a/src/cmus/events.rs b/src/cmus/events.rs index e1b74af..fe9f65e 100644 --- a/src/cmus/events.rs +++ b/src/cmus/events.rs @@ -1,8 +1,8 @@ use crate::cmus::player_settings::{AAAMode, PlayerSettings, Shuffle}; use crate::cmus::{Track, TrackStatus}; use crate::notification::Action; -use crate::process_template_placeholders; use crate::settings::Settings; +use crate::{process_template_placeholders, settings}; #[derive(Debug, PartialEq)] pub enum CmusEvent { @@ -51,19 +51,19 @@ impl CmusEvent { match self { StatusChanged(track, player_settings) => ( process_template_placeholders( - &settings.status_notification_body, + settings.status_notification_body(), track, player_settings, ), Action::Show, ), TrackChanged(track, player_settings) => ( - process_template_placeholders(&settings.body, track, player_settings), + process_template_placeholders(settings.body(), track, player_settings), Action::Show, ), VolumeChanged(track, player_settings) => ( process_template_placeholders( - &settings.volume_notification_body, + settings.volume_notification_body(), track, player_settings, ), @@ -74,7 +74,7 @@ impl CmusEvent { } ShuffleChanged(track, player_settings) => ( process_template_placeholders( - &settings.shuffle_notification_body, + settings.shuffle_notification_body(), track, player_settings, ), @@ -82,7 +82,7 @@ impl CmusEvent { ), RepeatChanged(track, player_settings) => ( process_template_placeholders( - &settings.repeat_notification_body, + settings.repeat_notification_body(), track, player_settings, ), @@ -90,7 +90,7 @@ impl CmusEvent { ), AAAMode(track, player_settings) => ( process_template_placeholders( - &settings.aaa_mode_notification_body, + settings.aaa_mode_notification_body(), track, player_settings, ), @@ -105,19 +105,19 @@ impl CmusEvent { match self { StatusChanged(track, player_settings) => ( process_template_placeholders( - &settings.status_notification_summary, + settings.status_notification_summary(), track, player_settings, ), Action::Show, ), TrackChanged(track, player_settings) => ( - process_template_placeholders(&settings.summary, track, player_settings), + process_template_placeholders(settings.summary(), track, player_settings), Action::Show, ), VolumeChanged(track, player_settings) => ( process_template_placeholders( - &settings.volume_notification_summary, + settings.volume_notification_summary(), track, player_settings, ), @@ -128,7 +128,7 @@ impl CmusEvent { } ShuffleChanged(track, player_settings) => ( process_template_placeholders( - &settings.shuffle_notification_summary, + settings.shuffle_notification_summary(), track, player_settings, ), @@ -136,7 +136,7 @@ impl CmusEvent { ), RepeatChanged(track, player_settings) => ( process_template_placeholders( - &settings.repeat_notification_summary, + settings.repeat_notification_summary(), track, player_settings, ), @@ -144,7 +144,7 @@ impl CmusEvent { ), AAAMode(track, player_settings) => ( process_template_placeholders( - &settings.aaa_mode_notification_summary, + settings.aaa_mode_notification_summary(), track, player_settings, ), diff --git a/src/cmus/mod.rs b/src/cmus/mod.rs index d170da6..218b3b8 100644 --- a/src/cmus/mod.rs +++ b/src/cmus/mod.rs @@ -14,11 +14,11 @@ use thiserror::Error; use typed_builder::TypedBuilder; pub trait TemplateProcessor { - fn process(&self, template: &String) -> String; + fn process(&self, template: String) -> String; /// Returns a vector of keys found in the template. /// The keys are the strings between curly braces. - fn get_keys(template: &String) -> Vec { + fn get_keys(template: &str) -> Vec { let mut keys = Vec::new(); // Just a buffer to store the keys. let mut key = String::new(); // Just a buffer to build the key. @@ -92,16 +92,16 @@ impl TemplateProcessor for Track { /// The template is a string with placeholders that will be replaced with the track metadata. /// The unknown placeholders will be skipped (don't replaced with anything, because they are maybe placeholders for player settings). #[inline(always)] - fn process(&self, template: &String) -> String { + fn process(&self, template: String) -> String { #[cfg(feature = "debug")] { info!("Processing the template placeholders."); debug!("Template: {template}"); debug!("Track: {self:?}"); } - let mut processed = template.clone(); + let mut processed = template.to_string(); - Self::get_keys(template).iter().for_each(|key| { + Self::get_keys(template.as_str()).iter().for_each(|key| { #[cfg(feature = "debug")] debug!("Replacing the placeholder {{{key}}} with its matching value."); // Replace the key with their matching value if exists, if not replace with the empty string. diff --git a/src/cmus/player_settings.rs b/src/cmus/player_settings.rs index 07eaa04..46520c7 100644 --- a/src/cmus/player_settings.rs +++ b/src/cmus/player_settings.rs @@ -42,7 +42,7 @@ impl TemplateProcessor for PlayerSettings { /// If the key is unknown, it will be replaced with an empty string. /// This function should be used after the track metadata placeholders have been replaced. #[inline(always)] - fn process(&self, template: &String) -> String { + fn process(&self, template: String) -> String { #[cfg(feature = "debug")] { info!("Processing template: {}", template); @@ -50,7 +50,7 @@ impl TemplateProcessor for PlayerSettings { } let mut processed = template.clone(); - Self::get_keys(template).iter().for_each(|key| { + Self::get_keys(template.as_str()).iter().for_each(|key| { let value = match key.as_str() { "repeat" => self.repeat.to_string(), "repeat_current" => self.repeat_current.to_string(), diff --git a/src/lib.rs b/src/lib.rs index b8ddcbb..c3517c8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -212,12 +212,12 @@ fn search(search_directory: &str, matcher: ®ex::Regex) -> std::io::Result String { let res = track.process(template); - player_settings.process(&res) + player_settings.process(res) } #[cfg(test)] diff --git a/src/notification.rs b/src/notification.rs index bf4b848..bb66bd5 100644 --- a/src/notification.rs +++ b/src/notification.rs @@ -3,7 +3,7 @@ use crate::cmus::player_settings::PlayerSettings; use crate::cmus::query::CmusQueryResponse; use crate::cmus::{Track, TrackStatus}; use crate::settings::Settings; -use crate::{process_template_placeholders, track_cover, TrackCover}; +use crate::{process_template_placeholders, settings, track_cover, TrackCover}; #[cfg(feature = "debug")] use log::{debug, info}; use notify_rust::Notification; @@ -94,8 +94,7 @@ impl NotificationsHandler { // Reset the notification self.notification = Notification::new(); self.notification - .appname("cmus-notify") - .timeout(self.settings.timeout as i32 * 1000) + .appname(self.settings.app_name().as_str()) .hint(notify_rust::Hint::Category("music".to_string())) .hint(notify_rust::Hint::DesktopEntry("cmus.desktop".to_string())) .hint(notify_rust::Hint::Resident(true)); @@ -103,7 +102,7 @@ impl NotificationsHandler { // Get the track cover and set it to notification track_cover( &track.path, - self.settings.depth, + self.settings.depth(), self.settings.force_use_external_cover, self.settings.no_use_external_cover, ) diff --git a/src/settings.rs b/src/settings.rs index dd9502e..3c2878b 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -3,28 +3,29 @@ use clap::Parser; use log::{debug, info}; use serde::{Deserialize, Serialize}; -const NOTIFICATION_TIMEOUT: u8 = 5; -const NOTIFICATION_BODY: &str = +pub const NOTIFICATION_TIMEOUT: u8 = 5; +pub const NOTIFICATION_BODY: &str = "Playing: {title} \n album: {album} \n Artist: {artist} - {year}"; -const NOTIFICATION_SUMMARY: &str = "{title}"; -const NOTIFICATION_APP_NAME: &str = "C* Music Player"; -const DEFAULT_MAX_DEPTH: u8 = 3; -const DEFAULT_INTERVAL_TIME: u64 = 1000; // 1000 ms -const DEFAULT_STATUS_CHANGE_NOTIFICATION_BODY: &str = "{status}"; -const DEFAULT_STATUS_CHANGE_NOTIFICATION_SUMMARY: &str = "Status changed"; -const DEFAULT_STATUS_CHANGE_NOTIFICATION_TIMEOUT: u8 = 1; -const DEFAULT_VOLUME_CHANGE_NOTIFICATION_BODY: &str = "Volume changed to {volume}%"; -const DEFAULT_VOLUME_CHANGE_NOTIFICATION_SUMMARY: &str = "Volume changed"; -const DEFAULT_VOLUME_CHANGE_NOTIFICATION_TIMEOUT: u8 = 1; -const DEFAULT_SHUFFLE_NOTIFICATION_BODY: &str = "Shuffle mode changed to {shuffle}"; -const DEFAULT_SHUFFLE_NOTIFICATION_SUMMARY: &str = "Shuffle mode changed"; -const DEFAULT_SHUFFLE_NOTIFICATION_TIMEOUT: u8 = 1; -const DEFAULT_REPEAT_NOTIFICATION_BODY: &str = "Repeat mode changed to {repeat}"; -const DEFAULT_REPEAT_NOTIFICATION_SUMMARY: &str = "Repeat mode changed"; -const DEFAULT_REPEAT_NOTIFICATION_TIMEOUT: u8 = 1; -const DEFAULT_AAAMODE_NOTIFICATION_BODY: &str = "AAA mode changed to {aaa_mode}"; -const DEFAULT_AAAMODE_NOTIFICATION_SUMMARY: &str = "AAA mode changed"; -const DEFAULT_AAAMODE_NOTIFICATION_TIMEOUT: u8 = 1; +pub const NOTIFICATION_SUMMARY: &str = "{title}"; +pub const NOTIFICATION_APP_NAME: &str = "C* Music Player"; +pub const DEFAULT_REMOTE_COMMAND: &str = "cmus-remote"; +pub const DEFAULT_MAX_DEPTH: u8 = 3; +pub const DEFAULT_INTERVAL_TIME: u64 = 1000; // 1000 ms +pub const DEFAULT_STATUS_CHANGE_NOTIFICATION_BODY: &str = "{status}"; +pub const DEFAULT_STATUS_CHANGE_NOTIFICATION_SUMMARY: &str = "Status changed"; +pub const DEFAULT_STATUS_CHANGE_NOTIFICATION_TIMEOUT: u8 = 1; +pub const DEFAULT_VOLUME_CHANGE_NOTIFICATION_BODY: &str = "Volume changed to {volume}%"; +pub const DEFAULT_VOLUME_CHANGE_NOTIFICATION_SUMMARY: &str = "Volume changed"; +pub const DEFAULT_VOLUME_CHANGE_NOTIFICATION_TIMEOUT: u8 = 1; +pub const DEFAULT_SHUFFLE_NOTIFICATION_BODY: &str = "Shuffle mode changed to {shuffle}"; +pub const DEFAULT_SHUFFLE_NOTIFICATION_SUMMARY: &str = "Shuffle mode changed"; +pub const DEFAULT_SHUFFLE_NOTIFICATION_TIMEOUT: u8 = 1; +pub const DEFAULT_REPEAT_NOTIFICATION_BODY: &str = "Repeat mode changed to {repeat}"; +pub const DEFAULT_REPEAT_NOTIFICATION_SUMMARY: &str = "Repeat mode changed"; +pub const DEFAULT_REPEAT_NOTIFICATION_TIMEOUT: u8 = 1; +pub const DEFAULT_AAAMODE_NOTIFICATION_BODY: &str = "AAA mode changed to {aaa_mode}"; +pub const DEFAULT_AAAMODE_NOTIFICATION_SUMMARY: &str = "AAA mode changed"; +pub const DEFAULT_AAAMODE_NOTIFICATION_TIMEOUT: u8 = 1; #[cfg(feature = "lyrics")] const DEFAULT_LYRICS_NOTIFICATION_BODY: &str = "{lyrics}"; #[cfg(feature = "lyrics")] @@ -34,8 +35,8 @@ const DEFAULT_LYRICS_NOTIFICATION_SUMMARY: &str = "Lyrics"; #[command(author, about, version, long_about = None)] pub struct Settings { /// The notification timeout, in seconds - #[arg(short, long, default_value_t = NOTIFICATION_TIMEOUT)] - pub timeout: u8, + #[arg(short, long)] + timeout: Option, /// Make the notification persistent, i.e. not disappear after a timeout (you can dismiss it manually) #[arg(short, long)] pub persistent: bool, @@ -48,7 +49,7 @@ pub struct Settings { /// you can give it the full path to an image file or a name of an icon from the current icon theme /// (e.g. "audio-x-generic" or "spotify-client") #[arg(short = 'i', long = "icon", default_value = None)] - pub notification_static_icon: Option, + notification_static_icon: Option, /// The path to look for the cover image, if not given, the cover will be searched in the track's directory /// for an image file with the name "cover". /// @@ -60,7 +61,7 @@ pub struct Settings { /// /// If you not specify the full path, the cover will be started from the track's directory. #[arg(short = 'w', long = "cover-path", default_value = None)] - pub cover_path: Option, + cover_path: Option, #[cfg(feature = "lyrics")] /// The lyrics file path, if not given, the lyrics will be searched in the track's directory /// for a text file with the name "lyrics", or with the same name as the track. @@ -73,24 +74,24 @@ pub struct Settings { /// /// If you not specify the full path, the lyrics will be started from the track's directory. #[arg(short = 'y', long, default_value = None)] - pub lyrics_path: Option, + lyrics_path: Option, /// The maximum path depth to search for the cover and lyrics files, /// if the files are not found in the track's directory, or the directory specified by the `--cover-path` /// or `--lyrics-path`* options, the program will search in the parent directory, /// and so on, until the maximum depth is reached. - #[arg(short, long, default_value_t = DEFAULT_MAX_DEPTH)] - pub depth: u8, + #[arg(short, long, default_value = None)] + depth: Option, /// The name of the app to use for the notification. - #[arg(short, long, default_value = NOTIFICATION_APP_NAME)] - pub app_name: String, + #[arg(short, long, default_value = None)] + pub app_name: Option, /// The summary of the notification. /// /// you can use the placeholder "{artist}" and "{album}" and "{title}" and "{track_number}" and /// "{disc_number}" and "{year}" and "{genre}" in the summary, they will be replaced with the corresponding metadata. /// but if the metadata is not available, the placeholder will be replaced with an empty string. /// e.g. "{artist} - {title}" - #[arg(short, long, default_value = NOTIFICATION_SUMMARY)] - pub summary: String, + #[arg(short, long, default_value = None)] + summary: Option, #[cfg(feature = "lyrics")] /// The body of the notification. /// @@ -109,8 +110,8 @@ pub struct Settings { /// the notification will be persistent, and you need to dismiss it manually tow times. /// /// Also you can use the simple html markup, if your notification server supports it. - #[arg(default_value = NOTIFICATION_BODY)] - pub body: String, + #[arg(default_value = None)] + body: Option, #[cfg(not(feature = "lyrics"))] /// The body of the notification. /// @@ -125,14 +126,14 @@ pub struct Settings { /// the notification will be persistent, and you need to dismiss it manually tow times. /// /// Also you can use the simple html markup, if your notification server supports it. - #[arg(default_value = NOTIFICATION_BODY)] - pub body: String, + #[arg(default_value = None)] + body: Option, /// The cmus-remote binary path, if not given, the program will search for it in the PATH environment variable. /// /// if you're using a custom package format like flatpak, or snap, you can give it the full run command (without any arguments), /// e.g. "flatpak run io.github.cmus.cmus", "snap run cmus" #[arg(short = 'b', long = "cmus-remote-bin", default_value = None)] - pub cmus_remote_bin_path: Option, + cmus_remote_bin_path: Option, /// The cmus socket address, if not given, the program will use the default socket address, which is "$XDG_RUNTIME_DIR/cmus-socket". #[arg(short = 'k', long = "cmus-socket", default_value = None)] pub cmus_socket_address: Option, @@ -149,8 +150,8 @@ pub struct Settings { /// but it will make the notification a little bit stupid, if you change the track manually, the notification will not update until the track duration time is reached. /// /// but I recommend 1s, it's not too fast, and not too slow, and it will not waste your CPU and battery. - #[arg(short = 'r', long, default_value_t = DEFAULT_INTERVAL_TIME)] - pub interval: u64, + #[arg(short = 'r', long, default_value = None)] + interval: Option, /// Link the program with cmus, if the cmus are not running, the program will exit. #[arg(short = 'l', long)] pub link: bool, @@ -176,98 +177,98 @@ pub struct Settings { /// you can use the placeholders like "{volume}" in the body, it will be replaced with the shuffle mode. /// /// If you leave it empty, the notification will not be shown. - #[arg(short = 'B', long, default_value = DEFAULT_VOLUME_CHANGE_NOTIFICATION_BODY)] - pub volume_notification_body: String, + #[arg(short = 'B', long, default_value = None)] + volume_notification_body: Option, /// The volume change notification summary. - #[arg(short = 'E', long, default_value = DEFAULT_VOLUME_CHANGE_NOTIFICATION_SUMMARY)] - pub volume_notification_summary: String, + #[arg(short = 'E', long, default_value = None)] + volume_notification_summary: Option, /// The time out of the volume change notification, in seconds. - #[arg(short = 'T', long, default_value_t = DEFAULT_VOLUME_CHANGE_NOTIFICATION_TIMEOUT)] - pub volume_notification_timeout: u8, + #[arg(short = 'T', long, default_value = None)] + volume_notification_timeout: Option, /// The shuffle mode change notification body. /// you can use the placeholders like "{shuffle}" in the body, it will be replaced with the shuffle mode. /// /// If you leave it empty, the notification will not be shown. - #[arg(short = 'S', long, default_value = DEFAULT_SHUFFLE_NOTIFICATION_BODY)] - pub shuffle_notification_body: String, + #[arg(short = 'S', long)] + shuffle_notification_body: Option, /// The shuffle mode change notification summary. /// you can use the placeholders like "{shuffle}" in the summary, it will be replaced with the shuffle mode. - #[arg(short = 'U', long, default_value = DEFAULT_SHUFFLE_NOTIFICATION_SUMMARY)] - pub shuffle_notification_summary: String, + #[arg(short = 'U', long)] + shuffle_notification_summary: Option, /// The time out of the shuffle mode change notification, in seconds. - #[arg(short = 'Y', long, default_value_t = DEFAULT_SHUFFLE_NOTIFICATION_TIMEOUT)] - pub shuffle_notification_timeout: u8, + #[arg(short = 'Y', long)] + shuffle_notification_timeout: Option, /// The repeat mode change notification body. /// you can use the placeholders like "{repeat}" in the body, it will be replaced with the repeat mode. /// /// If you leave it empty, the notification will not be shown. - #[arg(short = 'R', long, default_value = DEFAULT_REPEAT_NOTIFICATION_BODY)] - pub repeat_notification_body: String, + #[arg(short = 'R', long)] + repeat_notification_body: Option, /// The repeat mode change notification summary. /// you can use the placeholders like "{repeat}" in the summary, it will be replaced with the repeat mode. - #[arg(short = 'G', long, default_value = DEFAULT_REPEAT_NOTIFICATION_SUMMARY)] - pub repeat_notification_summary: String, + #[arg(short = 'G', long)] + repeat_notification_summary: Option, /// The time out of the repeat mode change notification, in seconds. - #[arg(short = 'H', long, default_value_t = DEFAULT_REPEAT_NOTIFICATION_TIMEOUT)] - pub repeat_notification_timeout: u8, + #[arg(short = 'H', long)] + repeat_notification_timeout: Option, /// The aaa mode change notification body. /// you can use the placeholders like "{aaa_mode}" in the body, it will be replaced with the aaa mode. /// /// If you leave it empty, the notification will not be shown. - #[arg(short = 'A', long, default_value = DEFAULT_AAAMODE_NOTIFICATION_BODY)] - pub aaa_mode_notification_body: String, + #[arg(short = 'A', long)] + aaa_mode_notification_body: Option, /// The aaa mode change notification summary. /// you can use the placeholders like "{aaa_mode}" in the summary, it will be replaced with the aaa mode. - #[arg(short = 'D', long, default_value = DEFAULT_AAAMODE_NOTIFICATION_SUMMARY)] - pub aaa_mode_notification_summary: String, + #[arg(short = 'D', long)] + aaa_mode_notification_summary: Option, /// The time out of the aaa mode change notification, in seconds. - #[arg(short = 'F', long, default_value_t = DEFAULT_AAAMODE_NOTIFICATION_TIMEOUT)] - pub aaa_mode_notification_timeout: u8, + #[arg(short = 'F', long)] + aaa_mode_notification_timeout: Option, #[cfg(feature = "lyrics")] /// The lyrics notification body, if you want to show the lyrics separate notification. /// you can use the placeholders like "{lyrics}" in the body, it will be replaced with the lyrics. /// /// If you leave it empty, the notification will not be shown. - #[arg(short = 'L', long, default_value = DEFAULT_LYRICS_NOTIFICATION_BODY)] - pub lyrics_notification_body: String, + #[arg(short = 'L', long)] + lyrics_notification_body: Option, #[cfg(feature = "lyrics")] /// The lyrics notification summary, if you want to show the lyrics separate notification. /// you can use the placeholders like "{lyrics}" in the summary, it will be replaced with the lyrics. - #[arg(short = 'M', long, default_value = DEFAULT_LYRICS_NOTIFICATION_SUMMARY)] - pub lyrics_notification_summary: String, + #[arg(short = 'M', long)] + lyrics_notification_summary: Option, /// The status change notification body. /// you can use the placeholders like "{status}" in the body, it will be replaced with the aaa mode. /// /// If you leave it empty, the notification will not be shown. - #[arg(short = 'O', long, default_value = DEFAULT_STATUS_CHANGE_NOTIFICATION_BODY)] - pub status_notification_body: String, + #[arg(short = 'O', long)] + status_notification_body: Option, /// The status change notification summary. /// you can use the placeholders like "{status}" in the summary, it will be replaced with the aaa mode. - #[arg(short = 'P', long, default_value = DEFAULT_STATUS_CHANGE_NOTIFICATION_SUMMARY)] - pub status_notification_summary: String, + #[arg(short = 'P', long)] + status_notification_summary: Option, /// The time out of the status change notification, in seconds. - #[arg(short = 'Q', long, default_value_t = DEFAULT_STATUS_CHANGE_NOTIFICATION_TIMEOUT)] - pub status_notification_timeout: u8, + #[arg(short = 'Q', long)] + status_notification_timeout: Option, } impl Default for Settings { fn default() -> Self { Self { - timeout: NOTIFICATION_TIMEOUT, + timeout: Some(NOTIFICATION_TIMEOUT), persistent: false, show_track_cover: true, notification_static_icon: None, cover_path: None, #[cfg(feature = "lyrics")] lyrics_path: None, - depth: DEFAULT_MAX_DEPTH, - app_name: NOTIFICATION_APP_NAME.to_string(), - summary: NOTIFICATION_SUMMARY.to_string(), - body: NOTIFICATION_BODY.to_string(), - cmus_remote_bin_path: None, + depth: Some(DEFAULT_MAX_DEPTH), + app_name: Some(NOTIFICATION_APP_NAME.to_string()), + summary: Some(NOTIFICATION_SUMMARY.to_string()), + body: Some(NOTIFICATION_BODY.to_string()), + cmus_remote_bin_path: Some(DEFAULT_REMOTE_COMMAND.to_string()), cmus_socket_address: None, cmus_socket_password: None, - interval: DEFAULT_INTERVAL_TIME, + interval: Some(DEFAULT_INTERVAL_TIME), link: false, force_use_external_cover: false, #[cfg(feature = "lyrics")] @@ -276,25 +277,29 @@ impl Default for Settings { #[cfg(feature = "lyrics")] no_use_external_lyrics: false, show_player_notifications: false, - volume_notification_body: DEFAULT_VOLUME_CHANGE_NOTIFICATION_BODY.to_string(), - volume_notification_summary: DEFAULT_VOLUME_CHANGE_NOTIFICATION_SUMMARY.to_string(), - volume_notification_timeout: DEFAULT_VOLUME_CHANGE_NOTIFICATION_TIMEOUT, - shuffle_notification_body: DEFAULT_SHUFFLE_NOTIFICATION_BODY.to_string(), - shuffle_notification_summary: DEFAULT_SHUFFLE_NOTIFICATION_SUMMARY.to_string(), - shuffle_notification_timeout: DEFAULT_SHUFFLE_NOTIFICATION_TIMEOUT, - repeat_notification_body: DEFAULT_REPEAT_NOTIFICATION_BODY.to_string(), - repeat_notification_summary: DEFAULT_REPEAT_NOTIFICATION_SUMMARY.to_string(), - repeat_notification_timeout: DEFAULT_REPEAT_NOTIFICATION_TIMEOUT, - aaa_mode_notification_body: DEFAULT_AAAMODE_NOTIFICATION_BODY.to_string(), - aaa_mode_notification_summary: DEFAULT_AAAMODE_NOTIFICATION_SUMMARY.to_string(), - aaa_mode_notification_timeout: DEFAULT_AAAMODE_NOTIFICATION_TIMEOUT, + volume_notification_body: Some(DEFAULT_VOLUME_CHANGE_NOTIFICATION_BODY.to_string()), + volume_notification_summary: Some( + DEFAULT_VOLUME_CHANGE_NOTIFICATION_SUMMARY.to_string(), + ), + volume_notification_timeout: Some(DEFAULT_VOLUME_CHANGE_NOTIFICATION_TIMEOUT), + shuffle_notification_body: Some(DEFAULT_SHUFFLE_NOTIFICATION_BODY.to_string()), + shuffle_notification_summary: Some(DEFAULT_SHUFFLE_NOTIFICATION_SUMMARY.to_string()), + shuffle_notification_timeout: Some(DEFAULT_SHUFFLE_NOTIFICATION_TIMEOUT), + repeat_notification_body: Some(DEFAULT_REPEAT_NOTIFICATION_BODY.to_string()), + repeat_notification_summary: Some(DEFAULT_REPEAT_NOTIFICATION_SUMMARY.to_string()), + repeat_notification_timeout: Some(DEFAULT_REPEAT_NOTIFICATION_TIMEOUT), + aaa_mode_notification_body: Some(DEFAULT_AAAMODE_NOTIFICATION_BODY.to_string()), + aaa_mode_notification_summary: Some(DEFAULT_AAAMODE_NOTIFICATION_SUMMARY.to_string()), + aaa_mode_notification_timeout: Some(DEFAULT_AAAMODE_NOTIFICATION_TIMEOUT), #[cfg(feature = "lyrics")] - lyrics_notification_body: DEFAULT_LYRICS_NOTIFICATION_BODY.to_string(), + lyrics_notification_body: Some(DEFAULT_LYRICS_NOTIFICATION_BODY.to_string()), #[cfg(feature = "lyrics")] - lyrics_notification_summary: DEFAULT_LYRICS_NOTIFICATION_SUMMARY.to_string(), - status_notification_body: DEFAULT_STATUS_CHANGE_NOTIFICATION_BODY.to_string(), - status_notification_summary: DEFAULT_STATUS_CHANGE_NOTIFICATION_SUMMARY.to_string(), - status_notification_timeout: DEFAULT_STATUS_CHANGE_NOTIFICATION_TIMEOUT, + lyrics_notification_summary: Some(DEFAULT_LYRICS_NOTIFICATION_SUMMARY.to_string()), + status_notification_body: Some(DEFAULT_STATUS_CHANGE_NOTIFICATION_BODY.to_string()), + status_notification_summary: Some( + DEFAULT_STATUS_CHANGE_NOTIFICATION_SUMMARY.to_string(), + ), + status_notification_timeout: Some(DEFAULT_STATUS_CHANGE_NOTIFICATION_TIMEOUT), } } } @@ -310,7 +315,7 @@ impl Settings { #[cfg(feature = "debug")] info!("Loading config and parsing args..."); // load config file - let cfg: Self = match confy::load("cmus-notify", "config") { + let mut cfg: Self = match confy::load("cmus-notify", "config") { Ok(cfg) => cfg, Err(err) => { eprintln!("Failed to load config: {}", err); @@ -325,7 +330,7 @@ impl Settings { } // parse the args - let mut args = Settings::parse(); + let args = Settings::parse(); #[cfg(feature = "debug")] { @@ -334,178 +339,238 @@ impl Settings { } // Combine the config and args(the args will override the config) - if args.timeout == NOTIFICATION_TIMEOUT { - #[cfg(feature = "debug")] - debug!( - "The user not override the timeout, using the config's timeout. timeout: {}", - cfg.timeout - ); - args.timeout = cfg.timeout; - } - if args.persistent == false { - #[cfg(feature = "debug")] - debug!("The user not override the persistent, using the config's persistent. persistent: {}", cfg.persistent); - args.persistent = cfg.persistent; - } - if args.show_track_cover == true { - #[cfg(feature = "debug")] - debug!("The user not override the show_track_cover, using the config's show_track_cover. show_track_cover: {}", cfg.show_track_cover); - args.show_track_cover = cfg.show_track_cover; - } - args.notification_static_icon = args + cfg.timeout = args.timeout.or(cfg.timeout); + cfg.persistent = args.persistent || cfg.persistent; + cfg.show_track_cover = args.show_track_cover || cfg.show_track_cover; + cfg.notification_static_icon = args .notification_static_icon .or(cfg.notification_static_icon); - args.cover_path = args.cover_path.or(cfg.cover_path); + cfg.cover_path = args.cover_path.or(cfg.cover_path); #[cfg(feature = "lyrics")] - if args.lyrics_path == None { + if args.lyrics_path != None { #[cfg(feature = "debug")] debug!("The user not override the lyrics_path, using the config's lyrics_path. lyrics_path: {:?}", cfg.lyrics_path); - args.lyrics_path = cfg.lyrics_path; + cfg.lyrics_path = args.lyrics_path; } - if args.depth == DEFAULT_MAX_DEPTH { - #[cfg(feature = "debug")] - debug!( - "The user not override the depth, using the config's depth. depth: {}", - cfg.depth - ); - args.depth = cfg.depth; - } - if args.app_name == NOTIFICATION_APP_NAME { - #[cfg(feature = "debug")] - debug!( - "The user not override the app_name, using the config's app_name. app_name: {}", - cfg.app_name - ); - args.app_name = cfg.app_name; - } - if args.summary == NOTIFICATION_SUMMARY { - #[cfg(feature = "debug")] - debug!( - "The user not override the summary, using the config's summary. summary: {}", - cfg.summary - ); - args.summary = cfg.summary; - } - if args.body == NOTIFICATION_BODY { - #[cfg(feature = "debug")] - debug!( - "The user not override the body, using the config's body. body: {}", - cfg.body - ); - args.body = cfg.body; - } - args.cmus_remote_bin_path = args.cmus_remote_bin_path.or(cfg.cmus_remote_bin_path); - args.cmus_socket_address = args.cmus_socket_address.or(cfg.cmus_socket_address); - args.cmus_socket_password = args.cmus_socket_password.or(cfg.cmus_socket_password); - if args.interval == DEFAULT_INTERVAL_TIME { - #[cfg(feature = "debug")] - debug!( - "The user not override the interval, using the config's interval. interval: {}", - cfg.interval - ); - args.interval = cfg.interval; - } - if args.link == false { - #[cfg(feature = "debug")] - debug!( - "The user not override the link, using the config's link. link: {}", - cfg.link - ); - args.link = cfg.link; - } - if args.force_use_external_cover == false { - #[cfg(feature = "debug")] - debug!("The user not override the force_use_external_cover, using the config's force_use_external_cover. force_use_external_cover: {}", cfg.force_use_external_cover); - args.force_use_external_cover = cfg.force_use_external_cover; - } + cfg.depth = args.depth.or(cfg.depth); + cfg.app_name = args.app_name.or(cfg.app_name); + cfg.summary = args.summary.or(cfg.summary); + cfg.body = args.body.or(cfg.body); + cfg.cmus_remote_bin_path = args.cmus_remote_bin_path.or(cfg.cmus_remote_bin_path); + cfg.cmus_socket_address = args.cmus_socket_address.or(cfg.cmus_socket_address); + cfg.cmus_socket_password = args.cmus_socket_password.or(cfg.cmus_socket_password); + cfg.interval = args.interval.or(cfg.interval); + cfg.link = args.link || cfg.link; + cfg.force_use_external_cover = + args.force_use_external_cover || cfg.force_use_external_cover; #[cfg(feature = "lyrics")] - if args.force_use_external_lyrics == false { - #[cfg(feature = "debug")] - debug!("The user not override the force_use_external_lyrics, using the config's force_use_external_lyrics. force_use_external_lyrics: {}", cfg.force_use_external_lyrics); - args.force_use_external_lyrics = cfg.force_use_external_lyrics; - } - if args.no_use_external_cover == false { - #[cfg(feature = "debug")] - debug!("The user not override the no_use_external_cover, using the config's no_use_external_cover. no_use_external_cover: {}", cfg.no_use_external_cover); - args.no_use_external_cover = cfg.no_use_external_cover; - } - #[cfg(feature = "lyrics")] - if args.no_use_external_lyrics == false { - #[cfg(feature = "debug")] - debug!("The user not override the no_use_external_lyrics, using the config's no_use_external_lyrics. no_use_external_lyrics: {}", cfg.no_use_external_lyrics); - args.no_use_external_lyrics = cfg.no_use_external_lyrics; - } - if args.show_player_notifications == false { - #[cfg(feature = "debug")] - debug!("The user not override the show_player_notifications, using the config's show_player_notifications. show_player_notifications: {}", cfg.show_player_notifications); - args.show_player_notifications = cfg.show_player_notifications; - } - if args.volume_notification_body == DEFAULT_VOLUME_CHANGE_NOTIFICATION_BODY { - #[cfg(feature = "debug")] - debug!("The user not override the volume_notification_body, using the config's volume_notification_body. volume_notification_body: {}", cfg.volume_notification_body); - args.volume_notification_body = cfg.volume_notification_body; - } - if args.volume_notification_summary == DEFAULT_VOLUME_CHANGE_NOTIFICATION_SUMMARY { - #[cfg(feature = "debug")] - debug!("The user not override the volume_notification_summary, using the config's volume_notification_summary. volume_notification_summary: {}", cfg.volume_notification_summary); - args.volume_notification_summary = cfg.volume_notification_summary; - } - if args.volume_notification_timeout == DEFAULT_VOLUME_CHANGE_NOTIFICATION_TIMEOUT { - #[cfg(feature = "debug")] - debug!("The user not override the volume_notification_timeout, using the config's volume_notification_timeout. volume_notification_timeout: {}", cfg.volume_notification_timeout); - args.volume_notification_timeout = cfg.volume_notification_timeout; - } - if args.shuffle_notification_body == DEFAULT_SHUFFLE_NOTIFICATION_BODY { - #[cfg(feature = "debug")] - debug!("The user not override the shuffle_notification_body, using the config's shuffle_notification_body. shuffle_notification_body: {}", cfg.shuffle_notification_body); - args.shuffle_notification_body = cfg.shuffle_notification_body; - } - if args.shuffle_notification_summary == DEFAULT_SHUFFLE_NOTIFICATION_SUMMARY { - #[cfg(feature = "debug")] - debug!("The user not override the shuffle_notification_summary, using the config's shuffle_notification_summary. shuffle_notification_summary: {}", cfg.shuffle_notification_summary); - args.shuffle_notification_summary = cfg.shuffle_notification_summary; - } - if args.shuffle_notification_timeout == DEFAULT_SHUFFLE_NOTIFICATION_TIMEOUT { - #[cfg(feature = "debug")] - debug!("The user not override the shuffle_notification_timeout, using the config's shuffle_notification_timeout. shuffle_notification_timeout: {}", cfg.shuffle_notification_timeout); - args.shuffle_notification_timeout = cfg.shuffle_notification_timeout; - } - if args.repeat_notification_body == DEFAULT_REPEAT_NOTIFICATION_BODY { - #[cfg(feature = "debug")] - debug!("The user not override the repeat_notification_body, using the config's repeat_notification_body. repeat_notification_body: {}", cfg.repeat_notification_body); - args.repeat_notification_body = cfg.repeat_notification_body; - } - if args.repeat_notification_summary == DEFAULT_REPEAT_NOTIFICATION_SUMMARY { - #[cfg(feature = "debug")] - debug!("The user not override the repeat_notification_summary, using the config's repeat_notification_summary. repeat_notification_summary: {}", cfg.repeat_notification_summary); - args.repeat_notification_summary = cfg.repeat_notification_summary; - } - if args.repeat_notification_timeout == DEFAULT_REPEAT_NOTIFICATION_TIMEOUT { - #[cfg(feature = "debug")] - debug!("The user not override the repeat_notification_timeout, using the config's repeat_notification_timeout. repeat_notification_timeout: {}", cfg.repeat_notification_timeout); - args.repeat_notification_timeout = cfg.repeat_notification_timeout; - } - if args.aaa_mode_notification_body == DEFAULT_AAAMODE_NOTIFICATION_BODY { - #[cfg(feature = "debug")] - debug!("The user not override the aaa_mode_notification_body, using the config's aaa_mode_notification_body. aaa_mode_notification_body: {}", cfg.aaa_mode_notification_body); - args.aaa_mode_notification_body = cfg.aaa_mode_notification_body; - } - if args.aaa_mode_notification_summary == DEFAULT_AAAMODE_NOTIFICATION_SUMMARY { - #[cfg(feature = "debug")] - debug!("The user not override the aaa_mode_notification_summary, using the config's aaa_mode_notification_summary. aaa_mode_notification_summary: {}", cfg.aaa_mode_notification_summary); - args.aaa_mode_notification_summary = cfg.aaa_mode_notification_summary; - } - if args.aaa_mode_notification_timeout == DEFAULT_AAAMODE_NOTIFICATION_TIMEOUT { - #[cfg(feature = "debug")] - debug!("The user not override the aaa_mode_notification_timeout, using the config's aaa_mode_notification_timeout. aaa_mode_notification_timeout: {}", cfg.aaa_mode_notification_timeout); - args.aaa_mode_notification_timeout = cfg.aaa_mode_notification_timeout; + { + cfg.force_use_external_lyrics = + args.force_use_external_lyrics || cfg.force_use_external_lyrics; + cfg.no_use_external_lyrics = args.no_use_external_lyrics || cfg.no_use_external_lyrics; } + cfg.no_use_external_cover = args.no_use_external_cover || cfg.no_use_external_cover; + cfg.show_player_notifications = + args.show_player_notifications || cfg.show_player_notifications; + cfg.volume_notification_body = args + .volume_notification_body + .or(cfg.volume_notification_body); + cfg.volume_notification_summary = args + .volume_notification_summary + .or(cfg.volume_notification_summary); + cfg.volume_notification_timeout = args + .volume_notification_timeout + .or(cfg.volume_notification_timeout); + cfg.shuffle_notification_body = args + .shuffle_notification_body + .or(cfg.shuffle_notification_body); + cfg.shuffle_notification_summary = args + .shuffle_notification_summary + .or(cfg.shuffle_notification_summary); + cfg.shuffle_notification_timeout = args + .shuffle_notification_timeout + .or(cfg.shuffle_notification_timeout); + cfg.repeat_notification_body = args + .repeat_notification_body + .or(cfg.repeat_notification_body); + cfg.repeat_notification_summary = args + .repeat_notification_summary + .or(cfg.repeat_notification_summary); + cfg.repeat_notification_timeout = args + .repeat_notification_timeout + .or(cfg.repeat_notification_timeout); + cfg.aaa_mode_notification_body = args + .aaa_mode_notification_body + .or(cfg.aaa_mode_notification_body); + cfg.aaa_mode_notification_summary = args + .aaa_mode_notification_summary + .or(cfg.aaa_mode_notification_summary); + cfg.aaa_mode_notification_timeout = args + .aaa_mode_notification_timeout + .or(cfg.aaa_mode_notification_timeout); #[cfg(feature = "debug")] - info!("The final settings: {:?}", args); + info!("The final settings: {:?}", cfg); - args + cfg + } + + #[inline(always)] + pub fn timeout(&self) -> u8 { + self.timeout.unwrap_or(NOTIFICATION_TIMEOUT) + } + + #[inline(always)] + pub fn app_name(&self) -> String { + self.app_name + .as_ref() + .unwrap_or(&NOTIFICATION_APP_NAME.to_string()) + .to_string() + } + + #[inline(always)] + pub fn interval(&self) -> u64 { + self.interval.unwrap_or(DEFAULT_INTERVAL_TIME) + } + + #[inline(always)] + pub fn depth(&self) -> u8 { + self.depth.unwrap_or(DEFAULT_MAX_DEPTH) + } + + #[inline(always)] + pub fn remote_bin_path(&self) -> String { + self.cmus_remote_bin_path + .as_ref() + .unwrap_or(&DEFAULT_REMOTE_COMMAND.to_string()) + .to_string() + } + + #[inline(always)] + pub fn status_notification_summary(&self) -> String { + self.status_notification_summary + .as_ref() + .unwrap_or(&DEFAULT_STATUS_CHANGE_NOTIFICATION_SUMMARY.to_string()) + .to_string() + } + + #[inline(always)] + pub fn status_notification_body(&self) -> String { + self.status_notification_body + .as_ref() + .unwrap_or(&DEFAULT_STATUS_CHANGE_NOTIFICATION_BODY.to_string()) + .to_string() + } + + #[inline(always)] + pub fn status_notification_timeout(&self) -> u8 { + self.status_notification_timeout + .unwrap_or(DEFAULT_STATUS_CHANGE_NOTIFICATION_TIMEOUT) + } + + #[inline(always)] + pub fn summary(&self) -> String { + self.summary + .as_ref() + .unwrap_or(&NOTIFICATION_SUMMARY.to_string()) + .to_string() + } + + #[inline(always)] + pub fn body(&self) -> String { + self.body + .as_ref() + .unwrap_or(&NOTIFICATION_BODY.to_string()) + .to_string() + } + + #[inline(always)] + pub fn volume_notification_summary(&self) -> String { + self.volume_notification_summary + .as_ref() + .unwrap_or(&DEFAULT_VOLUME_CHANGE_NOTIFICATION_SUMMARY.to_string()) + .to_string() + } + + #[inline(always)] + pub fn volume_notification_body(&self) -> String { + self.volume_notification_body + .as_ref() + .unwrap_or(&DEFAULT_VOLUME_CHANGE_NOTIFICATION_BODY.to_string()) + .to_string() + } + + #[inline(always)] + pub fn volume_notification_timeout(&self) -> u8 { + self.volume_notification_timeout + .unwrap_or(DEFAULT_VOLUME_CHANGE_NOTIFICATION_TIMEOUT) + } + + #[inline(always)] + pub fn shuffle_notification_summary(&self) -> String { + self.shuffle_notification_summary + .as_ref() + .unwrap_or(&DEFAULT_SHUFFLE_NOTIFICATION_SUMMARY.to_string()) + .to_string() + } + + #[inline(always)] + pub fn shuffle_notification_body(&self) -> String { + self.shuffle_notification_body + .as_ref() + .unwrap_or(&DEFAULT_SHUFFLE_NOTIFICATION_BODY.to_string()) + .to_string() + } + + #[inline(always)] + pub fn shuffle_notification_timeout(&self) -> u8 { + self.shuffle_notification_timeout + .unwrap_or(DEFAULT_SHUFFLE_NOTIFICATION_TIMEOUT) + } + + #[inline(always)] + pub fn repeat_notification_summary(&self) -> String { + self.repeat_notification_summary + .as_ref() + .unwrap_or(&DEFAULT_REPEAT_NOTIFICATION_SUMMARY.to_string()) + .to_string() + } + + #[inline(always)] + pub fn repeat_notification_body(&self) -> String { + self.repeat_notification_body + .as_ref() + .unwrap_or(&DEFAULT_REPEAT_NOTIFICATION_BODY.to_string()) + .to_string() + } + + #[inline(always)] + pub fn repeat_notification_timeout(&self) -> u8 { + self.repeat_notification_timeout + .unwrap_or(DEFAULT_REPEAT_NOTIFICATION_TIMEOUT) + } + + #[inline(always)] + pub fn aaa_mode_notification_summary(&self) -> String { + self.aaa_mode_notification_summary + .as_ref() + .unwrap_or(&DEFAULT_AAAMODE_NOTIFICATION_SUMMARY.to_string()) + .to_string() + } + + #[inline(always)] + pub fn aaa_mode_notification_body(&self) -> String { + self.aaa_mode_notification_body + .as_ref() + .unwrap_or(&DEFAULT_AAAMODE_NOTIFICATION_BODY.to_string()) + .to_string() + } + + #[inline(always)] + pub fn aaa_mode_notification_timeout(&self) -> u8 { + self.aaa_mode_notification_timeout + .unwrap_or(DEFAULT_AAAMODE_NOTIFICATION_TIMEOUT) } }