use crate::logging::log_mpd_command;
use mpd_client::{client::CommandError, commands, responses::PlayState};
use std::fmt;
#[derive(Debug, Clone)]
pub enum MPDAction {
TogglePlayPause,
Next,
Previous,
Random,
Repeat,
Single,
Consume,
VolumeUp,
VolumeUpFine,
VolumeDown,
VolumeDownFine,
ToggleMute,
SeekForward,
SeekBackward,
ClearQueue,
RemoveFromQueue,
MoveUpInQueue,
MoveDownInQueue,
QueueUp,
QueueDown,
PlaySelected,
Quit,
Refresh,
SwitchToQueueMenu,
SwitchToArtists,
SwitchToAlbums,
SwitchToYears,
SwitchToGenres,
SwitchPanelLeft,
SwitchPanelRight,
NavigateUp,
NavigateDown,
ToggleAlbumExpansion,
AddSongToQueue,
CycleModeLeft,
CycleModeRight,
ScrollUp,
ScrollDown,
GoToTop,
GoToBottom,
ToggleBitPerfect,
}
impl fmt::Display for MPDAction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
MPDAction::TogglePlayPause => write!(f, "TogglePlayPause"),
MPDAction::Next => write!(f, "Next"),
MPDAction::Previous => write!(f, "Previous"),
MPDAction::Random => write!(f, "Random"),
MPDAction::Repeat => write!(f, "Repeat"),
MPDAction::Single => write!(f, "Single"),
MPDAction::Consume => write!(f, "Consume"),
MPDAction::VolumeUp => write!(f, "VolumeUp"),
MPDAction::VolumeUpFine => write!(f, "VolumeUpFine"),
MPDAction::VolumeDown => write!(f, "VolumeDown"),
MPDAction::VolumeDownFine => write!(f, "VolumeDownFine"),
MPDAction::ToggleMute => write!(f, "ToggleMute"),
MPDAction::SeekForward => write!(f, "SeekForward"),
MPDAction::SeekBackward => write!(f, "SeekBackward"),
MPDAction::ClearQueue => write!(f, "ClearQueue"),
MPDAction::RemoveFromQueue => write!(f, "RemoveFromQueue"),
MPDAction::MoveUpInQueue => write!(f, "MoveUpInQueue"),
MPDAction::MoveDownInQueue => write!(f, "MoveDownInQueue"),
MPDAction::QueueUp => write!(f, "QueueUp"),
MPDAction::QueueDown => write!(f, "QueueDown"),
MPDAction::PlaySelected => write!(f, "PlaySelected"),
MPDAction::Quit => write!(f, "Quit"),
MPDAction::Refresh => write!(f, "Refresh"),
MPDAction::SwitchToQueueMenu => write!(f, "SwitchToQueueMenu"),
MPDAction::SwitchToArtists => write!(f, "SwitchToArtists"),
MPDAction::SwitchToAlbums => write!(f, "SwitchToAlbums"),
MPDAction::SwitchToYears => write!(f, "SwitchToYears"),
MPDAction::SwitchToGenres => write!(f, "SwitchToGenres"),
MPDAction::SwitchPanelLeft => write!(f, "SwitchPanelLeft"),
MPDAction::SwitchPanelRight => write!(f, "SwitchPanelRight"),
MPDAction::NavigateUp => write!(f, "NavigateUp"),
MPDAction::NavigateDown => write!(f, "NavigateDown"),
MPDAction::ToggleAlbumExpansion => write!(f, "ToggleAlbumExpansion"),
MPDAction::AddSongToQueue => write!(f, "AddSongToQueue"),
MPDAction::CycleModeLeft => write!(f, "CycleModeLeft"),
MPDAction::CycleModeRight => write!(f, "CycleModeRight"),
MPDAction::ScrollUp => write!(f, "ScrollUp"),
MPDAction::ScrollDown => write!(f, "ScrollDown"),
MPDAction::GoToTop => write!(f, "GoToTop"),
MPDAction::GoToBottom => write!(f, "GoToBottom"),
MPDAction::ToggleBitPerfect => write!(f, "ToggleBitPerfect"),
}
}
}
impl MPDAction {
fn is_mpd_command(&self) -> bool {
matches!(
self,
MPDAction::TogglePlayPause
| MPDAction::Next
| MPDAction::Previous
| MPDAction::Random
| MPDAction::Repeat
| MPDAction::Single
| MPDAction::Consume
| MPDAction::VolumeUp
| MPDAction::VolumeUpFine
| MPDAction::VolumeDown
| MPDAction::VolumeDownFine
| MPDAction::ToggleMute
| MPDAction::SeekForward
| MPDAction::SeekBackward
| MPDAction::ClearQueue
)
}
pub async fn execute(
&self,
client: &mpd_client::Client,
app: &mut crate::App,
) -> Result<(), CommandError> {
let result = self.execute_inner(client, app).await;
if self.is_mpd_command() {
match &result {
Ok(()) => log_mpd_command(&self.to_string(), true, None),
Err(e) => log_mpd_command(&self.to_string(), false, Some(&e.to_string())),
}
}
result
}
async fn execute_inner(
&self,
client: &mpd_client::Client,
app: &mut crate::App,
) -> Result<(), CommandError> {
let cached_status = app.mpd_status.as_ref();
let config = &app.config;
match self {
MPDAction::TogglePlayPause => {
let current_state = if let Some(status) = cached_status {
status.state
} else {
client.command(commands::Status).await?.state
};
match current_state {
PlayState::Playing => {
client.command(commands::SetPause(true)).await?;
}
_ => {
client.command(commands::Play::current()).await?;
}
}
}
MPDAction::Next => {
client.command(commands::Next).await?;
}
MPDAction::Previous => {
client.command(commands::Previous).await?;
}
MPDAction::VolumeUp => {
let increment = config.mpd.volume_increment as u8;
let current_volume = if let Some(status) = cached_status {
status.volume
} else {
client.command(commands::Status).await?.volume
};
let new_volume = std::cmp::min(100, current_volume + increment);
client.command(commands::SetVolume(new_volume)).await?;
}
MPDAction::VolumeUpFine => {
let increment = config.mpd.volume_increment_fine as u8;
let current_volume = if let Some(status) = cached_status {
status.volume
} else {
client.command(commands::Status).await?.volume
};
let new_volume = std::cmp::min(100, current_volume + increment);
client.command(commands::SetVolume(new_volume)).await?;
}
MPDAction::VolumeDown => {
let increment = config.mpd.volume_increment as u8;
let current_volume = if let Some(status) = cached_status {
status.volume
} else {
client.command(commands::Status).await?.volume
};
let new_volume = current_volume.saturating_sub(increment);
client.command(commands::SetVolume(new_volume)).await?;
}
MPDAction::VolumeDownFine => {
let increment = config.mpd.volume_increment_fine as u8;
let current_volume = if let Some(status) = cached_status {
status.volume
} else {
client.command(commands::Status).await?.volume
};
let new_volume = current_volume.saturating_sub(increment);
client.command(commands::SetVolume(new_volume)).await?;
}
MPDAction::ToggleMute => {
let current_volume = if let Some(status) = cached_status {
status.volume
} else {
client.command(commands::Status).await?.volume
};
if current_volume > 0 {
app.vol_before_mute = current_volume;
client.command(commands::SetVolume(0)).await?;
} else {
client
.command(commands::SetVolume(app.vol_before_mute))
.await?;
}
}
MPDAction::SeekForward => {
client
.command(commands::Seek(commands::SeekMode::Forward(
std::time::Duration::from_secs(5),
)))
.await?;
}
MPDAction::SeekBackward => {
client
.command(commands::Seek(commands::SeekMode::Backward(
std::time::Duration::from_secs(5),
)))
.await?;
}
MPDAction::ClearQueue => {
client.command(commands::ClearQueue).await?;
}
MPDAction::RemoveFromQueue => {
}
MPDAction::Random => {
let random = if let Some(status) = cached_status {
status.random
} else {
client.command(commands::Status).await?.random
};
client.command(commands::SetRandom(!random)).await?;
}
MPDAction::Repeat => {
let repeat = if let Some(status) = cached_status {
status.repeat
} else {
client.command(commands::Status).await?.repeat
};
client.command(commands::SetRepeat(!repeat)).await?;
}
MPDAction::Single => {
let single = if let Some(status) = cached_status {
status.single
} else {
client.command(commands::Status).await?.single
};
let new_single = match single {
commands::SingleMode::Enabled => commands::SingleMode::Disabled,
_ => commands::SingleMode::Enabled,
};
client.command(commands::SetSingle(new_single)).await?;
}
MPDAction::Consume => {
let consume = if let Some(status) = cached_status {
status.consume
} else {
client.command(commands::Status).await?.consume
};
client.command(commands::SetConsume(!consume)).await?;
}
MPDAction::QueueUp
| MPDAction::QueueDown
| MPDAction::PlaySelected
| MPDAction::Quit
| MPDAction::Refresh
| MPDAction::MoveUpInQueue
| MPDAction::MoveDownInQueue
| MPDAction::SwitchToQueueMenu
| MPDAction::SwitchToArtists
| MPDAction::SwitchToAlbums
| MPDAction::SwitchToYears
| MPDAction::SwitchToGenres
| MPDAction::SwitchPanelLeft
| MPDAction::SwitchPanelRight
| MPDAction::NavigateUp
| MPDAction::NavigateDown
| MPDAction::ToggleAlbumExpansion
| MPDAction::AddSongToQueue
| MPDAction::CycleModeLeft
| MPDAction::CycleModeRight
| MPDAction::ScrollUp
| MPDAction::ScrollDown
| MPDAction::GoToTop
| MPDAction::GoToBottom
| MPDAction::ToggleBitPerfect => {
}
}
Ok(())
}
}