Adjust tui to new protobuf spec

This commit is contained in:
chmanie 2023-06-02 15:36:08 +02:00
parent 47b788bf9c
commit 8d01cfce73
2 changed files with 74 additions and 140 deletions

View File

@ -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<UiItem>,
list_state: ListState,
}
@ -187,8 +187,8 @@ impl ListView for QueueView {
impl QueueView {
// FIXME: implement skip on server
fn skip(&self, tx: &Sender<MessageFromUi>) {
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<MessageFromUi>) {
@ -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<MessageFromUi>) {
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<u32>,
elapsed: Option<f64>,
playing_state: TrackPlayState,
play_state: PlayState,
track: Option<Track>,
}
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);
fn update_play_state(&mut self, play_state: PlayState) {
self.play_state = play_state;
}
let changed = if let Some(current_track) = &self.track {
current_track.uuid != next_track.uuid
} else {
true
};
if changed {
fn update_position(&mut self, pos: TrackPosition) {}
fn update_track(&mut self, active: Option<Track>) {
if let Some(track) = &active {
Notification::new()
.summary("Crabidy playing")
.body(&format!("{} by {}", next_track.title, next_track.artist))
// FIXME: album
.body(&format!("{} by {}", track.title, track.artist))
.show()
.unwrap();
self.track = Some(next_track);
}
}
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<MessageFromUi>, rx: Receiver<MessageToUi>) {
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) => {}
},
MessageToUi::TrackStreamUpdate(active_track) => {
app.now_playing.update(active_track);
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);
}
}
_ => {}
},
}
}
@ -713,10 +691,10 @@ fn ui<B: Backend>(f: &mut Frame<B>, 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![

View File

@ -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<String, LibraryNode>,
client: CrabidyServiceClient<Channel>,
pub queue_updates_stream: Streaming<GetQueueUpdatesResponse>,
pub track_updates_stream: Streaming<GetTrackUpdatesResponse>,
pub update_stream: Streaming<GetUpdateStreamResponse>,
}
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<String, LibraryNode> = 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<Channel>,
) -> Streaming<GetQueueUpdatesResponse> {
) -> Streaming<GetUpdateStreamResponse> {
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<Channel>,
) -> Streaming<GetTrackUpdatesResponse> {
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<dyn Error>> {
let replace_with_node_request = Request::new(ReplaceWithNodeRequest {
uuid: uuid.to_string(),
pub async fn replace_queue(&mut self, uuid: &str) -> Result<(), Box<dyn Error>> {
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<dyn Error>> {
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<dyn Error>> {
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(())
}