Implement shuffle, repeat and their indicators

This commit is contained in:
chmanie 2023-06-10 13:00:22 +02:00
parent ef22a84021
commit a65ad793dc
2 changed files with 48 additions and 4 deletions

View File

@ -3,7 +3,8 @@ mod rpc;
use crabidy_core::proto::crabidy::{ use crabidy_core::proto::crabidy::{
crabidy_service_client::CrabidyServiceClient, crabidy_service_client::CrabidyServiceClient,
get_update_stream_response::Update as StreamUpdate, GetLibraryNodeRequest, get_update_stream_response::Update as StreamUpdate, GetLibraryNodeRequest,
InitResponse as InitialData, LibraryNode, PlayState, Queue, QueueTrack, Track, TrackPosition, InitResponse as InitialData, LibraryNode, PlayState, Queue, QueueModifiers, QueueTrack, Track,
TrackPosition,
}; };
use crossterm::{ use crossterm::{
@ -386,6 +387,7 @@ impl LibraryView {
struct NowPlayingView { struct NowPlayingView {
play_state: PlayState, play_state: PlayState,
duration: Option<Duration>, duration: Option<Duration>,
modifiers: QueueModifiers,
position: Option<Duration>, position: Option<Duration>,
track: Option<Track>, track: Option<Track>,
} }
@ -409,6 +411,9 @@ impl NowPlayingView {
} }
self.track = active; self.track = active;
} }
fn update_modifiers(&mut self, mods: &QueueModifiers) {
self.modifiers = mods.clone();
}
} }
struct App { struct App {
@ -438,6 +443,7 @@ impl App {
let now_playing = NowPlayingView { let now_playing = NowPlayingView {
play_state: PlayState::Unspecified, play_state: PlayState::Unspecified,
duration: None, duration: None,
modifiers: QueueModifiers::default(),
position: None, position: None,
track: None, track: None,
}; };
@ -480,6 +486,8 @@ enum MessageFromUi {
TogglePlay, TogglePlay,
ChangeVolume(f32), ChangeVolume(f32),
ToggleMute, ToggleMute,
ToggleShuffle,
ToggleRepeat,
} }
async fn poll( async fn poll(
@ -531,6 +539,12 @@ async fn poll(
MessageFromUi::ToggleMute => { MessageFromUi::ToggleMute => {
rpc_client.toggle_mute().await? rpc_client.toggle_mute().await?
} }
MessageFromUi::ToggleShuffle => {
rpc_client.toggle_shuffle().await?
}
MessageFromUi::ToggleRepeat => {
rpc_client.toggle_repeat().await?
}
} }
} }
Some(resp) = rpc_client.update_stream.next() => { Some(resp) = rpc_client.update_stream.next() => {
@ -614,6 +628,9 @@ fn run_ui(tx: Sender<MessageFromUi>, rx: Receiver<MessageToUi>) {
if let Some(ps) = PlayState::from_i32(init_data.play_state) { if let Some(ps) = PlayState::from_i32(init_data.play_state) {
app.now_playing.update_play_state(ps); app.now_playing.update_play_state(ps);
} }
if let Some(mods) = init_data.mods {
app.now_playing.update_modifiers(&mods);
}
} }
MessageToUi::Update(update) => match update { MessageToUi::Update(update) => match update {
StreamUpdate::Queue(queue) => { StreamUpdate::Queue(queue) => {
@ -629,7 +646,11 @@ fn run_ui(tx: Sender<MessageFromUi>, rx: Receiver<MessageToUi>) {
app.now_playing.update_play_state(ps); app.now_playing.update_play_state(ps);
} }
} }
_ => {} StreamUpdate::Mods(mods) => {
app.now_playing.update_modifiers(&mods);
}
StreamUpdate::Mute(_) => { /* FIXME: implement */ }
StreamUpdate::Volume(_) => { /* FIXME: implement */ }
}, },
} }
} }
@ -663,6 +684,12 @@ fn run_ui(tx: Sender<MessageFromUi>, rx: Receiver<MessageToUi>) {
(_, KeyModifiers::NONE, KeyCode::Char('m')) => { (_, KeyModifiers::NONE, KeyCode::Char('m')) => {
tx.send(MessageFromUi::ToggleMute); tx.send(MessageFromUi::ToggleMute);
} }
(_, KeyModifiers::NONE, KeyCode::Char('z')) => {
tx.send(MessageFromUi::ToggleShuffle);
}
(_, KeyModifiers::NONE, KeyCode::Char('x')) => {
tx.send(MessageFromUi::ToggleRepeat);
}
(_, KeyModifiers::CONTROL, KeyCode::Char('n')) => { (_, KeyModifiers::CONTROL, KeyCode::Char('n')) => {
app.queue.play_next(); app.queue.play_next();
} }
@ -875,8 +902,12 @@ fn ui<B: Backend>(f: &mut Frame<B>, app: &mut App) {
Some(album) => album.title.to_string(), Some(album) => album.title.to_string(),
None => "No album".to_string(), None => "No album".to_string(),
}; };
let mods = format!(
"Shuffle: {}, Repeat {}",
&app.now_playing.modifiers.shuffle, &app.now_playing.modifiers.repeat
);
vec![ vec![
Spans::from(Span::raw("")), Spans::from(Span::raw(mods)),
Spans::from(Span::raw(play_text)), Spans::from(Span::raw(play_text)),
Spans::from(vec![ Spans::from(vec![
Span::styled( Span::styled(

View File

@ -4,7 +4,7 @@ use crabidy_core::proto::crabidy::{
GetUpdateStreamRequest, GetUpdateStreamResponse, InitRequest, InitResponse, InsertRequest, GetUpdateStreamRequest, GetUpdateStreamResponse, InitRequest, InitResponse, InsertRequest,
LibraryNode, NextRequest, PrevRequest, QueueRequest, RemoveRequest, ReplaceRequest, LibraryNode, NextRequest, PrevRequest, QueueRequest, RemoveRequest, ReplaceRequest,
RestartTrackRequest, SetCurrentRequest, SetCurrentResponse, ToggleMuteRequest, RestartTrackRequest, SetCurrentRequest, SetCurrentResponse, ToggleMuteRequest,
TogglePlayRequest, TogglePlayResponse, TogglePlayRequest, TogglePlayResponse, ToggleRepeatRequest, ToggleShuffleRequest,
}; };
use std::{ use std::{
@ -21,6 +21,7 @@ use tonic::{
Request, Streaming, Request, Streaming,
}; };
// FIXME: use anyhow + thiserror
#[derive(Debug)] #[derive(Debug)]
enum RpcClientError { enum RpcClientError {
NotFound, NotFound,
@ -175,6 +176,18 @@ impl RpcClient {
Ok(()) Ok(())
} }
pub async fn toggle_shuffle(&mut self) -> Result<(), Box<dyn Error>> {
let toggle_shuffle_request = Request::new(ToggleShuffleRequest {});
self.client.toggle_shuffle(toggle_shuffle_request).await?;
Ok(())
}
pub async fn toggle_repeat(&mut self) -> Result<(), Box<dyn Error>> {
let toggle_repeat_request = Request::new(ToggleRepeatRequest {});
self.client.toggle_repeat(toggle_repeat_request).await?;
Ok(())
}
pub async fn change_volume(&mut self, delta: f32) -> Result<(), Box<dyn Error>> { pub async fn change_volume(&mut self, delta: f32) -> Result<(), Box<dyn Error>> {
let change_volume_request = Request::new(ChangeVolumeRequest { delta }); let change_volume_request = Request::new(ChangeVolumeRequest { delta });
self.client.change_volume(change_volume_request).await?; self.client.change_volume(change_volume_request).await?;