diff --git a/README.md b/README.md
index 5d40623..730b370 100644
--- a/README.md
+++ b/README.md
@@ -55,6 +55,7 @@ You **must** have an existing premium Spotify subscription to use `ncspot`.
- [Proxy](#proxy)
- [Theming](#theming)
- [Track Formatting](#track-formatting)
+ - [Notification Formatting](#notification-formatting)
- [Cover Drawing](#cover-drawing)
- [Authentication](#authentication)
@@ -349,6 +350,7 @@ Possible configuration values are:
| `hide_display_names` | Hides spotify usernames in the library header and on playlists | `true`, `false` | `false` |
| `statusbar_format` | Formatting for tracks in the statusbar | See [track_formatting](#track-formatting) | `%artists - %track` |
| `[track_format]` | Set active fields shown in Library/Queue views | See [track formatting](#track-formatting) | |
+| `[notification_format]` | Set the text displayed in notifications[4] | See [notification formatting](#notification-formatting) | |
| `[theme]` | Custom theme | See [custom theme](#theming) | |
| `[keybindings]` | Custom keybindings | See [custom keybindings](#custom-keybindings) | |
@@ -506,6 +508,19 @@ right = "%album"
+### Notification Formatting
+`ncspot` also supports customizing the way notifications are displayed
+(which appear when compiled with the `notify` feature and `notify = true`).
+The title and body of the notification can be set, with `title` and `body`, or the default will be used.
+The formatting options are the same as those for [track formatting](#track-formatting) (`%artists`, `%title`, etc)
+
+Default configuration:
+```toml
+[notification_format]
+title = "%title"
+body = "%artists"
+```
+
## Cover Drawing
When compiled with the `cover` feature, `ncspot` can draw the album art of the
diff --git a/src/config.rs b/src/config.rs
index 6ad2925..a7ed946 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -50,6 +50,21 @@ impl TrackFormat {
}
}
+#[derive(Serialize, Deserialize, Debug, Default, Clone)]
+pub struct NotificationFormat {
+ pub title: Option,
+ pub body: Option,
+}
+
+impl NotificationFormat {
+ pub fn default() -> Self {
+ NotificationFormat {
+ title: Some(String::from("%title")),
+ body: Some(String::from("%artists")),
+ }
+ }
+}
+
#[derive(Clone, Serialize, Deserialize, Debug, Default)]
pub struct ConfigValues {
pub command_key: Option,
@@ -73,6 +88,7 @@ pub struct ConfigValues {
pub cover_max_scale: Option,
pub playback_state: Option,
pub track_format: Option,
+ pub notification_format: Option,
pub statusbar_format: Option,
pub library_tabs: Option>,
pub hide_display_names: Option,
diff --git a/src/main.rs b/src/main.rs
index 753447b..f0d9fba 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -175,10 +175,14 @@ async fn main() -> Result<(), String> {
println!("Connecting to Spotify..");
let spotify = spotify::Spotify::new(event_manager.clone(), credentials, cfg.clone());
- let queue = Arc::new(queue::Queue::new(spotify.clone(), cfg.clone()));
-
let library = Arc::new(Library::new(&event_manager, spotify.clone(), cfg.clone()));
+ let queue = Arc::new(queue::Queue::new(
+ spotify.clone(),
+ cfg.clone(),
+ library.clone(),
+ ));
+
#[cfg(feature = "mpris")]
let mpris_manager = Arc::new(mpris::MprisManager::new(
event_manager.clone(),
diff --git a/src/queue.rs b/src/queue.rs
index 84bb5f3..b3ed7a7 100644
--- a/src/queue.rs
+++ b/src/queue.rs
@@ -10,10 +10,11 @@ use notify_rust::{Hint, Notification, Urgency};
use rand::prelude::*;
use strum_macros::Display;
-use crate::config::PlaybackState;
+use crate::config::{Config, NotificationFormat, PlaybackState};
+use crate::library::Library;
use crate::model::playable::Playable;
+use crate::spotify::PlayerEvent;
use crate::spotify::Spotify;
-use crate::{config::Config, spotify::PlayerEvent};
#[derive(Display, Clone, Copy, PartialEq, Debug, Serialize, Deserialize)]
pub enum RepeatSetting {
@@ -38,10 +39,11 @@ pub struct Queue {
cfg: Arc,
#[cfg(feature = "notify")]
notification_id: Arc,
+ library: Arc,
}
impl Queue {
- pub fn new(spotify: Spotify, cfg: Arc) -> Queue {
+ pub fn new(spotify: Spotify, cfg: Arc, library: Arc) -> Queue {
let queue_state = cfg.state().queuestate.clone();
let playback_state = cfg.state().playback_state.clone();
let queue = Queue {
@@ -52,6 +54,7 @@ impl Queue {
cfg,
#[cfg(feature = "notify")]
notification_id: Arc::new(AtomicU32::new(0)),
+ library,
};
if let Some(playable) = queue.get_current() {
@@ -285,13 +288,27 @@ impl Queue {
if self.cfg.values().notify.unwrap_or(false) {
let notification_id = self.notification_id.clone();
std::thread::spawn({
- let track_name = track.to_string();
+ // use same parser as track_format, Playable::format
+ let format = self
+ .cfg
+ .values()
+ .notification_format
+ .clone()
+ .unwrap_or_default();
+ let default_title = NotificationFormat::default().title.unwrap();
+ let title = format.title.unwrap_or_else(|| default_title.clone());
+
+ let default_body = NotificationFormat::default().body.unwrap();
+ let body = format.body.unwrap_or_else(|| default_body.clone());
+
+ let summary_txt = Playable::format(track, &title, self.library.clone());
+ let body_txt = Playable::format(track, &body, self.library.clone());
let cover_url = if cfg!(feature = "cover") {
track.cover_url()
} else {
None
};
- move || send_notification(&track_name, cover_url, notification_id)
+ move || send_notification(&summary_txt, &body_txt, cover_url, notification_id)
});
}
}
@@ -432,7 +449,8 @@ impl Queue {
#[cfg(feature = "notify")]
pub fn send_notification(
- track_name: &str,
+ summary_txt: &str,
+ body_txt: &str,
cover_url: Option,
notification_id: Arc,
) {
@@ -441,7 +459,8 @@ pub fn send_notification(
let mut n = Notification::new();
n.appname("ncspot")
.id(current_notification_id)
- .summary(track_name);
+ .summary(summary_txt)
+ .body(body_txt);
// album cover image
if let Some(u) = cover_url {