Iimprove the articet

This commit is contained in:
Anas Elgarhy 2023-02-20 06:40:30 +02:00
parent b8af73ee0f
commit 9a5a93450a
No known key found for this signature in database
GPG key ID: 0501802A1D496528
6 changed files with 109 additions and 45 deletions

View file

@ -77,10 +77,12 @@ fn main() {
// Update the previous response.
previous_response = response;
match notifications_handler.show_notification(events, &previous_response) {
Ok(_) => {}
Err(e) => {
eprintln!("Error: {}", e);
if !events.is_empty() {
match notifications_handler.show_notification(events, &previous_response) {
Ok(_) => {}
Err(e) => {
eprintln!("Error: {}", e);
}
}
}
}

View file

@ -1,13 +1,13 @@
use crate::cmus::player_settings::{AAAMode, Shuffle};
use crate::cmus::player_settings::{AAAMode, PlayerSettings, Shuffle};
use crate::cmus::{Track, TrackStatus};
#[derive(Debug, PartialEq)]
pub enum CmusEvent {
StatusChanged(Track),
TrackChanged(Track),
VolumeChanged { left: u8, right: u8 },
PositionChanged(u32),
ShuffleChanged(Shuffle),
RepeatChanged(bool),
AAAMode(AAAMode),
StatusChanged(Track, PlayerSettings),
TrackChanged(Track, PlayerSettings),
VolumeChanged(Track, PlayerSettings),
PositionChanged(Track, PlayerSettings),
ShuffleChanged(Track, PlayerSettings),
RepeatChanged(Track, PlayerSettings),
AAAMode(Track, PlayerSettings),
}

View file

@ -12,12 +12,12 @@ use std::str::FromStr;
use thiserror::Error;
use typed_builder::TypedBuilder;
#[derive(Debug, PartialEq, Default)]
#[derive(Debug, PartialEq, Default, Clone)]
pub struct TrackMetadata {
tags: HashMap<String, String>,
}
#[derive(Debug, PartialEq, Default)]
#[derive(Debug, PartialEq, Default, Clone)]
pub enum TrackStatus {
Playing,
Paused,
@ -25,7 +25,7 @@ pub enum TrackStatus {
Stopped,
}
#[derive(Debug, TypedBuilder, PartialEq, Default)]
#[derive(Debug, TypedBuilder, PartialEq, Default, Clone)]
pub struct Track {
pub status: TrackStatus,
pub path: String,

View file

@ -4,7 +4,7 @@ use log::{debug, info};
use std::num::ParseIntError;
use std::str::FromStr;
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Clone)]
pub struct PlayerSettings {
pub repeat: bool,
pub repeat_current: bool,
@ -13,7 +13,7 @@ pub struct PlayerSettings {
pub volume: Volume,
}
#[derive(Debug, PartialEq, Default)]
#[derive(Debug, PartialEq, Default, Clone)]
pub enum Shuffle {
#[default]
Off,
@ -21,13 +21,13 @@ pub enum Shuffle {
Albums,
}
#[derive(Debug, PartialEq, Default)]
#[derive(Debug, PartialEq, Default, Clone)]
pub struct Volume {
pub left: u8,
pub right: u8,
}
#[derive(Debug, PartialEq, Default)]
#[derive(Debug, PartialEq, Default, Clone)]
pub enum AAAMode {
#[default]
All,

View file

@ -51,7 +51,7 @@ impl CmusQueryResponse {
if self.track_row.is_empty() || self.player_settings_row.is_empty() {
#[cfg(feature = "debug")]
info!("Cmus response is empty, returning empty events");
return Err(CmusError::NoEvents)
return Ok(Vec::new())
}
let mut events = Vec::new();
@ -59,6 +59,8 @@ impl CmusQueryResponse {
let track = self.track()?;
let other_track = other.track()?;
let other_player_settings = other.player_settings()?;
if track != other_track {
#[cfg(feature = "debug")]
debug!("Track changed: {:?} -> {:?}", other_track, track);
@ -66,7 +68,10 @@ impl CmusQueryResponse {
if track.path != other_track.path {
#[cfg(feature = "debug")]
debug!("Track changed: {:?} -> {:?}", other_track, track);
events.push(CmusEvent::TrackChanged(other_track));
events.push(CmusEvent::TrackChanged(
other_track.clone(),
other_player_settings.clone(),
));
// We don't need to check for other changes, since the track changed.
return Ok(events);
} else if track.status != other_track.status {
@ -75,19 +80,24 @@ impl CmusQueryResponse {
"Status changed: {:?} -> {:?}",
other_track.status, track.status
);
events.push(CmusEvent::StatusChanged(track));
events.push(CmusEvent::StatusChanged(
track.clone(),
other_player_settings.clone(),
));
} else if track.position != other_track.position {
#[cfg(feature = "debug")]
debug!(
"Position changed: {:?} -> {:?}",
other_track.position, track.position
);
events.push(CmusEvent::PositionChanged(other_track.position));
events.push(CmusEvent::PositionChanged(
track.clone(),
other_player_settings.clone(),
));
}
}
let player_settings = self.player_settings()?;
let other_player_settings = other.player_settings()?;
if player_settings != other_player_settings {
#[cfg(feature = "debug")]
@ -103,7 +113,10 @@ impl CmusQueryResponse {
other_player_settings.shuffle, player_settings.shuffle
);
events.push(CmusEvent::ShuffleChanged(player_settings.shuffle));
events.push(CmusEvent::ShuffleChanged(
other_track.clone(),
other_player_settings.clone(),
));
}
if player_settings.repeat != other_player_settings.repeat {
@ -113,7 +126,10 @@ impl CmusQueryResponse {
other_player_settings.repeat, player_settings.repeat
);
events.push(CmusEvent::RepeatChanged(player_settings.repeat));
events.push(CmusEvent::RepeatChanged(
other_track.clone(),
other_player_settings.clone(),
));
}
if player_settings.aaa_mode != other_player_settings.aaa_mode {
@ -123,7 +139,10 @@ impl CmusQueryResponse {
other_player_settings.aaa_mode, player_settings.aaa_mode
);
events.push(CmusEvent::AAAMode(player_settings.aaa_mode));
events.push(CmusEvent::AAAMode(
other_track.clone(),
other_player_settings.clone(),
));
}
if player_settings.volume != other_player_settings.volume {
@ -133,10 +152,7 @@ impl CmusQueryResponse {
other_player_settings.volume, player_settings.volume
);
events.push(CmusEvent::VolumeChanged {
left: player_settings.volume.left,
right: player_settings.volume.right,
});
events.push(CmusEvent::VolumeChanged(other_track, other_player_settings));
}
}

View file

@ -1,4 +1,5 @@
use crate::cmus::events::CmusEvent;
use crate::cmus::player_settings::PlayerSettings;
use crate::cmus::query::CmusQueryResponse;
use crate::cmus::{Track, TrackStatus};
use crate::settings::Settings;
@ -7,6 +8,12 @@ use crate::{process_template_placeholders, track_cover, TrackCover};
use log::{debug, info};
use notify_rust::Notification;
enum Action {
Show,
Update,
None,
}
pub struct NotificationsHandler {
cover_set: bool,
notification: Notification,
@ -33,26 +40,29 @@ impl NotificationsHandler {
//FIXME: Should check if the user has enabled the cover feature or use a static cover.
self.update_cover(&events[0], response);
let mut action = Action::None;
for event in events {
#[cfg(feature = "debug")]
info!("event: {:?}", event);
match event {
CmusEvent::StatusChanged(track) => {
CmusEvent::StatusChanged(track, player_settings) => {
#[cfg(feature = "debug")]
debug!("Status changed: {:?}", track.status);
self.build_status_notification(track);
self.notification.show()?;
action = self.build_status_notification(track, player_settings);
}
CmusEvent::TrackChanged(track) => {
CmusEvent::TrackChanged(track, player_settings) => {
#[cfg(feature = "debug")]
debug!("Track changed: {:?}", track);
self.build_track_notification(track)?
action = self.build_track_notification(track, player_settings);
}
CmusEvent::VolumeChanged(track, player_settings)
if self.settings.show_player_notifications =>
{
action = self.build_volume_notification(track, player_settings);
}
/*
CmusEvent::VolumeChanged { left, right } if settings.show_player_notifications => {
build_volume_notification(left, right, settings, notification)?
}
CmusEvent::PositionChanged(position) => todo!(),
CmusEvent::ShuffleChanged(shuffle) if settings.show_player_notifications => {
build_shuffle_notification(shuffle, settings, notification)?
@ -66,12 +76,26 @@ impl NotificationsHandler {
*/
_ => {}
}
match action {
Action::Show => {
let _ = self.notification.show()?;
}
Action::None => {}
_ => todo!(),
};
}
Ok(())
}
#[inline(always)]
fn build_status_notification(&mut self, track: Track) {
fn build_status_notification(
&mut self,
track: Track,
player_settings: PlayerSettings,
) -> Action {
// Set the summary and body of the notification.
self.notification
.summary(
@ -83,25 +107,47 @@ impl NotificationsHandler {
.as_str(),
)
.timeout(self.settings.status_notification_timeout as i32 * 1000);
Action::Show
}
#[inline(always)]
fn build_track_notification(&mut self, track: Track) -> Result<(), notify_rust::error::Error> {
fn build_track_notification(
&mut self,
track: Track,
player_settings: PlayerSettings,
) -> Action {
// Set the summary and body of the notification.
self.notification
.summary(process_template_placeholders(&self.settings.summary, &track).as_str())
.body(process_template_placeholders(&self.settings.body, &track).as_str());
let n = self.notification.show()?;
Action::Show
}
Ok(())
#[inline(always)]
fn build_volume_notification(
&mut self,
track: Track,
player_settings: PlayerSettings,
) -> Action {
self.notification
.summary(
process_template_placeholders(&self.settings.volume_notification_summary, &track)
.as_str(),
)
.body(
process_template_placeholders(&self.settings.volume_notification_body, &track)
.as_str(),
);
Action::Show
}
#[inline(always)]
fn update_cover(&mut self, first_event: &CmusEvent, response: &CmusQueryResponse) {
// If the track is changed, we need to update the cover.
match first_event {
CmusEvent::TrackChanged(track) => {
CmusEvent::TrackChanged(track, _) => {
self.set_cover(track);
}
_ => {
@ -133,7 +179,7 @@ impl NotificationsHandler {
self.settings.force_use_external_cover,
self.settings.no_use_external_cover,
)
.set_notification_image(&mut self.notification);
.set_notification_image(&mut self.notification);
// Flip the change flag
self.cover_set = true;
}