diff --git a/cbd-tui/src/main.rs b/cbd-tui/src/main.rs index 8c15e40..83c82f3 100644 --- a/cbd-tui/src/main.rs +++ b/cbd-tui/src/main.rs @@ -163,10 +163,10 @@ struct UiItem { } struct QueueView { - // FIXME: implement skip on server, remove current current_position: usize, list: Vec, list_state: ListState, + tx: Sender, } impl ListView for QueueView { @@ -184,14 +184,27 @@ impl ListView for QueueView { } impl QueueView { - fn skip(&self, tx: &Sender) { + fn play_next(&self) { if self.current_position < self.get_size() - 1 { - tx.send(MessageFromUi::Next); + self.tx.send(MessageFromUi::NextTrack); } } - fn play_selected(&self, tx: &Sender) { + fn play_prev(&self) { + if self.current_position > 0 { + self.tx.send(MessageFromUi::PrevTrack); + } + } + fn play_selected(&self) { if let Some(pos) = self.selected() { - tx.send(MessageFromUi::SetCurrentTrack(pos)); + self.tx.send(MessageFromUi::SetCurrentTrack(pos)); + } + } + fn insert_track(&mut self) { + todo!(); + } + fn remove_track(&mut self) { + if let Some(pos) = self.selected() { + self.tx.send(MessageFromUi::RemoveTrack(pos)); } } fn update_position(&mut self, pos: usize) { @@ -221,6 +234,7 @@ struct LibraryView { list_state: ListState, parent: Option, positions: HashMap, + tx: Sender, } impl ListView for LibraryView { @@ -250,21 +264,32 @@ impl LibraryView { } None } - fn ascend(&mut self, tx: &Sender) { + fn ascend(&mut self) { if let Some(parent) = self.parent.as_ref() { - tx.send(MessageFromUi::GetLibraryNode(parent.clone())); + self.tx.send(MessageFromUi::GetLibraryNode(parent.clone())); } } - fn dive(&mut self, tx: &Sender) { + fn dive(&mut self) { if let Some(item) = self.get_selected() { if let UiItemKind::Node = item.kind { - tx.send(MessageFromUi::GetLibraryNode(item.uuid.clone())); + self.tx + .send(MessageFromUi::GetLibraryNode(item.uuid.clone())); } } } - fn queue_replace_with_item(&mut self, tx: &Sender) { + fn queue_append(&mut self) { if let Some(item) = self.get_selected() { - tx.send(MessageFromUi::ReplaceQueue(item.uuid.clone())); + self.tx.send(MessageFromUi::AppendTrack(item.uuid.clone())); + } + } + fn queue_queue(&mut self) { + if let Some(item) = self.get_selected() { + self.tx.send(MessageFromUi::QueueTrack(item.uuid.clone())); + } + } + fn queue_replace(&mut self) { + if let Some(item) = self.get_selected() { + self.tx.send(MessageFromUi::ReplaceQueue(item.uuid.clone())); } } fn prev_selected(&self) -> usize { @@ -341,7 +366,7 @@ struct App { } impl App { - fn new() -> App { + fn new(tx: Sender) -> App { let mut library = LibraryView { title: "Library".to_string(), uuid: "node:/".to_string(), @@ -349,11 +374,13 @@ impl App { list_state: ListState::default(), positions: HashMap::new(), parent: None, + tx: tx.clone(), }; let queue = QueueView { current_position: 0, list: Vec::new(), list_state: ListState::default(), + tx, }; let now_playing = NowPlayingView { completion: None, @@ -388,10 +415,18 @@ enum MessageToUi { // FIXME: Rename this enum MessageFromUi { GetLibraryNode(String), - Next, + AppendTrack(String), + QueueTrack(String), + InsertTrack(String, usize), + RemoveTrack(usize), ReplaceQueue(String), + NextTrack, + PrevTrack, + RestartTrack, SetCurrentTrack(usize), TogglePlay, + ChangeVolume(f32), + ToggleMute, } async fn poll( @@ -407,19 +442,42 @@ async fn poll( tx.send(MessageToUi::ReplaceLibraryNode(node.clone())); } }, + MessageFromUi::AppendTrack(uuid) => { + rpc_client.append_track(&uuid).await? + } + MessageFromUi::QueueTrack(uuid) => { + rpc_client.queue_track(&uuid).await? + } + MessageFromUi::InsertTrack(uuid, pos) => { + rpc_client.insert_track(&uuid, pos).await? + } + MessageFromUi::RemoveTrack(pos) => { + rpc_client.remove_track(pos).await? + } MessageFromUi::ReplaceQueue(uuid) => { rpc_client.replace_queue(&uuid).await? } - MessageFromUi::TogglePlay => { - rpc_client.toggle_play().await? + MessageFromUi::NextTrack => { + rpc_client.next_track().await? + } + MessageFromUi::PrevTrack => { + rpc_client.prev_track().await? + } + MessageFromUi::RestartTrack => { + rpc_client.restart_track().await? } MessageFromUi::SetCurrentTrack(pos) => { rpc_client.set_current_track(pos).await? } - MessageFromUi::Next => { - // FIXME: + MessageFromUi::TogglePlay => { + rpc_client.toggle_play().await? + } + MessageFromUi::ChangeVolume(delta) => { + rpc_client.change_volume(delta).await? + } + MessageFromUi::ToggleMute => { + rpc_client.toggle_mute().await? } - } } Some(resp) = rpc_client.update_stream.next() => { @@ -482,7 +540,7 @@ fn run_ui(tx: Sender, rx: Receiver) { let mut terminal = Terminal::new(backend).unwrap(); // create app and run it - let mut app = App::new(); + let mut app = App::new(tx.clone()); let tick_rate = Duration::from_millis(100); let mut last_tick = Instant::now(); @@ -540,8 +598,23 @@ fn run_ui(tx: Sender, rx: Receiver) { (_, KeyModifiers::NONE, KeyCode::Char(' ')) => { tx.send(MessageFromUi::TogglePlay); } + (_, KeyModifiers::NONE, KeyCode::Char('p')) => { + tx.send(MessageFromUi::RestartTrack); + } + (_, KeyModifiers::SHIFT, KeyCode::Char('j')) => { + tx.send(MessageFromUi::ChangeVolume(-0.1)); + } + (_, KeyModifiers::SHIFT, KeyCode::Char('k')) => { + tx.send(MessageFromUi::ChangeVolume(0.1)); + } + (_, KeyModifiers::NONE, KeyCode::Char('m')) => { + tx.send(MessageFromUi::ToggleMute); + } (_, KeyModifiers::CONTROL, KeyCode::Char('n')) => { - app.queue.skip(&tx); + app.queue.play_next(); + } + (_, KeyModifiers::CONTROL, KeyCode::Char('p')) => { + app.queue.play_prev(); } (UiFocus::Library, KeyModifiers::NONE, KeyCode::Char('g')) => { app.library.first(); @@ -562,13 +635,19 @@ fn run_ui(tx: Sender, rx: Receiver) { app.library.up(); } (UiFocus::Library, KeyModifiers::NONE, KeyCode::Char('h')) => { - app.library.ascend(&tx); + app.library.ascend(); } (UiFocus::Library, KeyModifiers::NONE, KeyCode::Char('l')) => { - app.library.dive(&tx); + app.library.dive(); + } + (UiFocus::Library, KeyModifiers::NONE, KeyCode::Char('n')) => { + app.library.queue_queue(); + } + (UiFocus::Library, KeyModifiers::NONE, KeyCode::Char('a')) => { + app.library.queue_append(); } (UiFocus::Library, KeyModifiers::NONE, KeyCode::Enter) => { - app.library.queue_replace_with_item(&tx); + app.library.queue_replace(); } (UiFocus::Queue, KeyModifiers::NONE, KeyCode::Char('g')) => { app.queue.first(); @@ -589,7 +668,10 @@ fn run_ui(tx: Sender, rx: Receiver) { app.queue.up(); } (UiFocus::Queue, KeyModifiers::NONE, KeyCode::Enter) => { - app.queue.play_selected(&tx); + app.queue.play_selected(); + } + (UiFocus::Queue, KeyModifiers::NONE, KeyCode::Char('d')) => { + app.queue.remove_track(); } _ => {} } diff --git a/cbd-tui/src/rpc.rs b/cbd-tui/src/rpc.rs index c0914a1..06d574b 100644 --- a/cbd-tui/src/rpc.rs +++ b/cbd-tui/src/rpc.rs @@ -1,8 +1,10 @@ use crabidy_core::proto::crabidy::{ crabidy_service_client::CrabidyServiceClient, get_update_stream_response::Update, - GetLibraryNodeRequest, GetLibraryNodeResponse, GetUpdateStreamRequest, GetUpdateStreamResponse, - LibraryNode, ReplaceRequest, SetCurrentRequest, SetCurrentResponse, TogglePlayRequest, - TogglePlayResponse, InitRequest, InitResponse, + AppendRequest, ChangeVolumeRequest, GetLibraryNodeRequest, GetLibraryNodeResponse, + GetUpdateStreamRequest, GetUpdateStreamResponse, InitRequest, InitResponse, InsertRequest, + LibraryNode, NextRequest, PrevRequest, QueueRequest, RemoveRequest, ReplaceRequest, + RestartTrackRequest, SetCurrentRequest, SetCurrentResponse, ToggleMuteRequest, + TogglePlayRequest, TogglePlayResponse, }; use std::{ @@ -87,40 +89,77 @@ impl RpcClient { if self.library_node_cache.contains_key(uuid) { return Ok(self.library_node_cache.get(uuid)); } - let get_library_node_request = Request::new(GetLibraryNodeRequest { uuid: uuid.to_string(), }); - let response = self .client .get_library_node(get_library_node_request) .await?; - if let Some(library_node) = response.into_inner().node { self.library_node_cache .insert(uuid.to_string(), library_node); return Ok(self.library_node_cache.get(uuid)); } - Err(Box::new(RpcClientError::NotFound)) } + pub async fn append_track(&mut self, uuid: &str) -> Result<(), Box> { + let append_request = Request::new(AppendRequest { + uuid: vec![uuid.to_string()], + }); + self.client.append(append_request).await?; + Ok(()) + } + + pub async fn queue_track(&mut self, uuid: &str) -> Result<(), Box> { + let queue_request = Request::new(QueueRequest { + uuid: vec![uuid.to_string()], + }); + self.client.queue(queue_request).await?; + Ok(()) + } + + pub async fn insert_track(&mut self, uuid: &str, pos: usize) -> Result<(), Box> { + let insert_request = Request::new(InsertRequest { + uuid: vec![uuid.to_string()], + position: pos as u32, + }); + self.client.insert(insert_request).await?; + Ok(()) + } + + pub async fn remove_track(&mut self, pos: usize) -> Result<(), Box> { + let remove_request = Request::new(RemoveRequest { + positions: vec![pos as u32], + }); + self.client.remove(remove_request).await?; + Ok(()) + } + pub async fn replace_queue(&mut self, uuid: &str) -> Result<(), Box> { let replace_request = Request::new(ReplaceRequest { uuid: vec![uuid.to_string()], }); - - let response = self.client.replace(replace_request).await?; - + self.client.replace(replace_request).await?; Ok(()) } - pub async fn toggle_play(&mut self) -> Result<(), Box> { - let toggle_play_request = Request::new(TogglePlayRequest {}); + pub async fn next_track(&mut self) -> Result<(), Box> { + let next_request = Request::new(NextRequest {}); + self.client.next(next_request).await?; + Ok(()) + } - let response = self.client.toggle_play(toggle_play_request).await?; + pub async fn prev_track(&mut self) -> Result<(), Box> { + let prev_request = Request::new(PrevRequest {}); + self.client.prev(prev_request).await?; + Ok(()) + } + pub async fn restart_track(&mut self) -> Result<(), Box> { + let restart_track_request = Request::new(RestartTrackRequest {}); + self.client.restart_track(restart_track_request).await?; Ok(()) } @@ -128,9 +167,25 @@ impl RpcClient { let set_current_request = Request::new(SetCurrentRequest { position: pos as u32, }); + self.client.set_current(set_current_request).await?; + Ok(()) + } - let response = self.client.set_current(set_current_request).await?; + pub async fn toggle_play(&mut self) -> Result<(), Box> { + let toggle_play_request = Request::new(TogglePlayRequest {}); + self.client.toggle_play(toggle_play_request).await?; + Ok(()) + } + pub async fn change_volume(&mut self, delta: f32) -> Result<(), Box> { + let change_volume_request = Request::new(ChangeVolumeRequest { delta }); + self.client.change_volume(change_volume_request).await?; + Ok(()) + } + + pub async fn toggle_mute(&mut self) -> Result<(), Box> { + let toggle_mute_request = Request::new(ToggleMuteRequest {}); + self.client.toggle_mute(toggle_mute_request).await?; Ok(()) } }