diff --git a/cbd-tui/src/main.rs b/cbd-tui/src/main.rs index 7edffbf..5d9cdc3 100644 --- a/cbd-tui/src/main.rs +++ b/cbd-tui/src/main.rs @@ -1,9 +1,9 @@ mod rpc; use crabidy_core::proto::crabidy::{ - crabidy_service_client::CrabidyServiceClient, get_queue_updates_response::QueueUpdateResult, - ActiveTrack, GetLibraryNodeRequest, GetQueueUpdatesRequest, GetQueueUpdatesResponse, - GetTrackUpdatesResponse, LibraryNode, LibraryNodeState, Queue, Track, TrackPlayState, + crabidy_service_client::CrabidyServiceClient, + get_update_stream_response::Update as StreamUpdate, GetLibraryNodeRequest, LibraryNode, + PlayState, Queue, QueueTrack, Track, TrackPosition, }; use crossterm::{ @@ -165,7 +165,7 @@ struct UiItem { struct QueueView { // FIXME: implement skip on server, remove current - current: usize, + current_position: usize, list: Vec, list_state: ListState, } @@ -187,8 +187,8 @@ impl ListView for QueueView { impl QueueView { // FIXME: implement skip on server fn skip(&self, tx: &Sender) { - if self.current < self.get_size() - 1 { - tx.send(MessageFromUi::SetCurrentTrack(self.current + 1)); + if self.current_position < self.get_size() - 1 { + tx.send(MessageFromUi::SetCurrentTrack(self.current_position + 1)); } } fn play_selected(&self, tx: &Sender) { @@ -196,9 +196,11 @@ impl QueueView { tx.send(MessageFromUi::SetCurrentTrack(pos)); } } + fn update_position(&mut self, pos: usize) { + self.current_position = pos; + } fn update(&mut self, queue: Queue) { - // FIXME: rename current to current_pos in proto buf definition - self.current = queue.current as usize; + self.current_position = queue.current_position as usize; self.list = queue .tracks .iter() @@ -207,7 +209,7 @@ impl QueueView { uuid: t.uuid.clone(), title: format!("{} - {}", t.artist, t.title), kind: UiItemKind::Track, - active: i == queue.current as usize, + active: i == queue.current_position as usize, }) .collect(); @@ -265,7 +267,7 @@ impl LibraryView { } fn queue_replace_with_item(&mut self, tx: &Sender) { if let Some(item) = self.get_selected() { - tx.send(MessageFromUi::ReplaceWithItem(item.uuid.clone(), item.kind)); + tx.send(MessageFromUi::ReplaceQueue(item.uuid.clone())); } } fn prev_selected(&self) -> usize { @@ -314,36 +316,25 @@ impl LibraryView { struct NowPlayingView { completion: Option, elapsed: Option, - playing_state: TrackPlayState, + play_state: PlayState, track: Option, } impl NowPlayingView { - fn update(&mut self, active_track: ActiveTrack) { - self.playing_state = active_track.play_state(); - - if let Some(next_track) = active_track.track { - if let Some(duration) = next_track.duration { - self.completion = Some(active_track.completion); - self.elapsed = Some(active_track.completion as f64 / duration as f64); - } - - let changed = if let Some(current_track) = &self.track { - current_track.uuid != next_track.uuid - } else { - true - }; - - if changed { - Notification::new() - .summary("Crabidy playing") - .body(&format!("{} by {}", next_track.title, next_track.artist)) - .show() - .unwrap(); - - self.track = Some(next_track); - } + fn update_play_state(&mut self, play_state: PlayState) { + self.play_state = play_state; + } + fn update_position(&mut self, pos: TrackPosition) {} + fn update_track(&mut self, active: Option) { + if let Some(track) = &active { + Notification::new() + .summary("Crabidy playing") + // FIXME: album + .body(&format!("{} by {}", track.title, track.artist)) + .show() + .unwrap(); } + self.track = active; } } @@ -365,14 +356,14 @@ impl App { parent: None, }; let queue = QueueView { - current: 0, + current_position: 0, list: Vec::new(), list_state: ListState::default(), }; let now_playing = NowPlayingView { completion: None, elapsed: None, - playing_state: TrackPlayState::Unspecified, + play_state: PlayState::Unspecified, track: None, }; App { @@ -395,14 +386,13 @@ impl App { // FIXME: Rename this enum MessageToUi { ReplaceLibraryNode(LibraryNode), - QueueStreamUpdate(QueueUpdateResult), - TrackStreamUpdate(ActiveTrack), + Update(StreamUpdate), } // FIXME: Rename this enum MessageFromUi { GetLibraryNode(String), - ReplaceWithItem(String, UiItemKind), + ReplaceQueue(String), SetCurrentTrack(usize), TogglePlay, } @@ -420,15 +410,8 @@ async fn poll( tx.send(MessageToUi::ReplaceLibraryNode(node.clone())); } }, - MessageFromUi::ReplaceWithItem(uuid, kind) => { - match kind { - UiItemKind::Node => { - rpc_client.replace_queue_with_node(&uuid).await? - } - UiItemKind::Track => { - rpc_client.replace_queue_with_track(&uuid).await? - } - } + MessageFromUi::ReplaceQueue(uuid) => { + rpc_client.replace_queue(&uuid).await? } MessageFromUi::TogglePlay => { rpc_client.toggle_play().await? @@ -439,31 +422,19 @@ async fn poll( } } - Some(resp) = rpc_client.queue_updates_stream.next() => { + Some(resp) = rpc_client.update_stream.next() => { match resp { Ok(resp) => { - if let Some(res) = resp.queue_update_result { - tx.send_async(MessageToUi::QueueStreamUpdate(res)).await?; + if let Some(update) = resp.update { + tx.send_async(MessageToUi::Update(update)).await?; } } Err(_) => { - rpc_client.reconnect_queue_updates_stream().await; + rpc_client.reconnect_update_stream().await; } } } - Some(resp) = rpc_client.track_updates_stream.next() => { - match resp { - Ok(resp) => { - if let Some(active_track) = resp.active_track { - tx.send_async(MessageToUi::TrackStreamUpdate(active_track)).await?; - } - } - Err(_) => { - rpc_client.reconnect_track_updates_stream().await; - } - } - } } Ok(()) @@ -518,15 +489,22 @@ fn run_ui(tx: Sender, rx: Receiver) { MessageToUi::ReplaceLibraryNode(node) => { app.library.update(node); } - MessageToUi::QueueStreamUpdate(queue_update) => match queue_update { - QueueUpdateResult::Full(queue) => { + MessageToUi::Update(update) => match update { + StreamUpdate::Queue(queue) => { app.queue.update(queue); } - QueueUpdateResult::PositionChange(pos) => {} + StreamUpdate::QueueTrack(track) => { + app.now_playing.update_track(track.track); + app.queue.update_position(track.queue_position as usize); + } + StreamUpdate::Position(pos) => app.now_playing.update_position(pos), + StreamUpdate::PlayState(play_state) => { + if let Some(ps) = PlayState::from_i32(play_state) { + app.now_playing.update_play_state(ps); + } + } + _ => {} }, - MessageToUi::TrackStreamUpdate(active_track) => { - app.now_playing.update(active_track); - } } } @@ -713,10 +691,10 @@ fn ui(f: &mut Frame, app: &mut App) { .split(right_side[1]); let media_info_text = if let Some(track) = &app.now_playing.track { - let play_text = match &app.now_playing.playing_state { - TrackPlayState::Loading => "▼", - TrackPlayState::Paused => "■", - TrackPlayState::Playing => "♫", + let play_text = match &app.now_playing.play_state { + PlayState::Loading => "▼", + PlayState::Paused => "■", + PlayState::Playing => "♫", _ => "", }; vec![ diff --git a/cbd-tui/src/rpc.rs b/cbd-tui/src/rpc.rs index 7046373..cb152a3 100644 --- a/cbd-tui/src/rpc.rs +++ b/cbd-tui/src/rpc.rs @@ -1,9 +1,8 @@ use crabidy_core::proto::crabidy::{ - crabidy_service_client::CrabidyServiceClient, get_queue_updates_response::QueueUpdateResult, - GetLibraryNodeRequest, GetQueueUpdatesRequest, GetQueueUpdatesResponse, GetTrackUpdatesRequest, - GetTrackUpdatesResponse, LibraryNode, LibraryNodeState, ReplaceWithNodeRequest, - ReplaceWithNodeResponse, ReplaceWithTrackRequest, ReplaceWithTrackResponse, - SetCurrentTrackRequest, SetCurrentTrackResponse, TogglePlayRequest, + crabidy_service_client::CrabidyServiceClient, get_update_stream_response::Update, + GetLibraryNodeRequest, GetLibraryNodeResponse, GetUpdateStreamRequest, GetUpdateStreamResponse, + LibraryNode, ReplaceRequest, SetCurrentRequest, SetCurrentResponse, TogglePlayRequest, + TogglePlayResponse, }; use std::{ @@ -38,8 +37,7 @@ impl Error for RpcClientError {} pub struct RpcClient { library_node_cache: HashMap, client: CrabidyServiceClient, - pub queue_updates_stream: Streaming, - pub track_updates_stream: Streaming, + pub update_stream: Streaming, } impl RpcClient { @@ -47,24 +45,22 @@ impl RpcClient { let endpoint = Endpoint::from_static(addr).connect_lazy(); let mut client = CrabidyServiceClient::new(endpoint); - let queue_updates_stream = Self::get_queue_updates_stream(&mut client).await; - let track_updates_stream = Self::get_track_updates_stream(&mut client).await; + let update_stream = Self::get_update_stream(&mut client).await; let library_node_cache: HashMap = HashMap::new(); Ok(RpcClient { client, library_node_cache, - track_updates_stream, - queue_updates_stream, + update_stream, }) } - async fn get_queue_updates_stream( + async fn get_update_stream( client: &mut CrabidyServiceClient, - ) -> Streaming { + ) -> Streaming { loop { - let get_queue_updates_request = Request::new(GetQueueUpdatesRequest { timestamp: 0 }); - if let Ok(resp) = client.get_queue_updates(get_queue_updates_request).await { + let get_update_stream_request = Request::new(GetUpdateStreamRequest {}); + if let Ok(resp) = client.get_update_stream(get_update_stream_request).await { return resp.into_inner(); } else { tokio::time::sleep(Duration::from_secs(2)).await; @@ -72,31 +68,10 @@ impl RpcClient { } } - async fn get_track_updates_stream( - client: &mut CrabidyServiceClient, - ) -> Streaming { - loop { - let get_track_updates_request = Request::new(GetTrackUpdatesRequest { - type_whitelist: Vec::new(), - type_blacklist: Vec::new(), - updates_skipped: 0, - }); - if let Ok(resp) = client.get_track_updates(get_track_updates_request).await { - return resp.into_inner(); - } else { - tokio::time::sleep(Duration::from_secs(2)).await; - } - } - } - - pub async fn reconnect_queue_updates_stream(&mut self) { - let queue_updates_stream = Self::get_queue_updates_stream(&mut self.client).await; - mem::replace(&mut self.queue_updates_stream, queue_updates_stream); - } - - pub async fn reconnect_track_updates_stream(&mut self) { - let track_updates_stream = Self::get_track_updates_stream(&mut self.client).await; - mem::replace(&mut self.track_updates_stream, track_updates_stream); + pub async fn reconnect_update_stream(&mut self) { + let update_stream = Self::get_update_stream(&mut self.client).await; + // FIXME: apparently mem::replace doesn't do anything here + mem::replace(&mut self.update_stream, update_stream); } pub async fn get_library_node( @@ -125,28 +100,12 @@ impl RpcClient { Err(Box::new(RpcClientError::NotFound)) } - pub async fn replace_queue_with_node(&mut self, uuid: &str) -> Result<(), Box> { - let replace_with_node_request = Request::new(ReplaceWithNodeRequest { - uuid: uuid.to_string(), + 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_with_node(replace_with_node_request) - .await?; - - Ok(()) - } - - pub async fn replace_queue_with_track(&mut self, uuid: &str) -> Result<(), Box> { - let replace_with_track_request = Request::new(ReplaceWithTrackRequest { - uuid: uuid.to_string(), - }); - - let response = self - .client - .replace_with_track(replace_with_track_request) - .await?; + let response = self.client.replace(replace_request).await?; Ok(()) } @@ -160,14 +119,11 @@ impl RpcClient { } pub async fn set_current_track(&mut self, pos: usize) -> Result<(), Box> { - let set_current_track_request = Request::new(SetCurrentTrackRequest { + let set_current_request = Request::new(SetCurrentRequest { position: pos as u32, }); - let response = self - .client - .set_current_track(set_current_track_request) - .await?; + let response = self.client.set_current(set_current_request).await?; Ok(()) }