diff --git a/src/rust/amadeus-next/amalib/src/query.rs b/src/rust/amadeus-next/amalib/src/query.rs index 37029d1bdbe7009571bce0847e90d077c0a30f69..dba0e41b2df6063facb17d009e2ef7c398969b94 100644 --- a/src/rust/amadeus-next/amalib/src/query.rs +++ b/src/rust/amadeus-next/amalib/src/query.rs @@ -1,7 +1,7 @@ //! Contains files to create and build queries to send latter to lektord. use crate::*; -use std::string::ToString; +use std::{ops::Range, string::ToString}; #[derive(Debug, Clone, PartialEq, Eq)] pub(crate) enum LektorQueryLineType { @@ -26,6 +26,7 @@ pub enum LektorQuery { CurrentKara, PlaybackStatus, + ListQueue(Range<usize>), Play(usize), Pause, @@ -42,7 +43,11 @@ pub enum LektorQuery { ListAllPlaylists, ListPlaylist(String), - SearchKara(LektorUri), + GetKaraInfo(usize), + SearchKaraDatabase(LektorUri), + SearchKaraQueue(LektorUri), + SearchKaraPlaylist(String, LektorUri), + CountKaraDatabase(LektorUri), AddKara(LektorPriorityLevel, LektorUri), CreatePlaylist(String), @@ -137,7 +142,15 @@ impl LektorQuery { ConnectAsUser(_, cmd) | Continuation(_, cmd) => cmd.get_response_type(), - ListPlaylist(_) | SearchKara(_) => LektorKaraSetResponse::from_formated, + CountKaraDatabase(_) => LektorIntegerResponse::from_formated, + + SearchKaraQueue(_) + | SearchKaraPlaylist(_, _) + | ListQueue(_) + | ListPlaylist(_) + | SearchKaraDatabase(_) => LektorKaraSetResponse::from_formated, + + GetKaraInfo(_) => LektorKaraInfoResponse::from_formated, } } @@ -160,7 +173,10 @@ impl LektorQuery { } match self { // User commands - SearchKara(_) + SearchKaraDatabase(_) + | SearchKaraQueue(_) + | SearchKaraPlaylist(_, _) + | CountKaraDatabase(_) | AddKara(_, _) | PlaybackStatus | PlayNext @@ -177,6 +193,8 @@ impl LektorQuery { | Pause | UnPause | CurrentKara + | ListQueue(_) + | GetKaraInfo(_) | Ping => Ok(()), CreatePlaylist(str) @@ -197,7 +215,7 @@ impl LektorQuery { // Continuation commands Continuation(_, cmd) => match cmd.as_ref() { - ListAllPlaylists | SearchKara(_) | ListPlaylist(_) => Ok(()), + ListAllPlaylists | SearchKaraDatabase(_) | ListPlaylist(_) => Ok(()), _ => Err(format!("not a continuable command: {cmd:?}")), }, } @@ -250,7 +268,11 @@ impl LektorQuery { ListAllPlaylists => lkt_str!("listplaylists"), ListPlaylist(plt_name) => lkt_str!("listplaylist {plt_name}"), - SearchKara(uri) => lkt_str!("find {uri}"), + SearchKaraQueue(uri) => lkt_str!("playlistfind {uri}"), + CountKaraDatabase(uri) => lkt_str!("count {uri}"), + SearchKaraDatabase(uri) => lkt_str!("find {uri}"), + SearchKaraPlaylist(plt_name, uri) => lkt_str!("listplaylist {plt_name} {uri}"), + GetKaraInfo(id) => unimplemented!("get all infos for the kara id://{id}"), AddKara(LektorPriorityLevel::Add, uri) => lkt_str!("add {uri}"), AddKara(LektorPriorityLevel::Insert, uri) => lkt_str!("__insert {uri}"), @@ -261,6 +283,12 @@ impl LektorQuery { AddToPlaylist(name, uri) => lkt_str!("playlistadd {name} {uri}"), RemoveFromPlaylist(name, uri) => lkt_str!("playlistdelete {name} {uri}"), + ListQueue(Range { start, end }) => lkt_str!("playlist {start}:{end}"), + Continuation(start, query) if matches!(&**query, ListQueue(_)) => { + let ListQueue(Range { end, .. }) = &**query else { unreachable!() }; + lkt_str!("playlist {start}:{end}") + } + Continuation(cont, query) => { let query = query.format_query(); lkt_str!("{cont} {query}") diff --git a/src/rust/amadeus-next/amalib/src/response.rs b/src/rust/amadeus-next/amalib/src/response.rs index 626eea260e23ead8526faaecc2ffc27fb010cced..e732571626e47873af97968b34dbc5c09fb9ad71 100644 --- a/src/rust/amadeus-next/amalib/src/response.rs +++ b/src/rust/amadeus-next/amalib/src/response.rs @@ -41,6 +41,13 @@ impl LektorFormatedResponse { ret } + /// Pop all the content in the form of a key:pair vector. It's like the + /// [`LektorFormatedResponse::pop_raw`] function, but we splited each line + /// on the `: ` patern, and trimed all the things. + pub fn pop_dict(self) -> Vec<(String, String)> { + self.content + } + /// Get the raw content of the response. pub fn pop_raw(self) -> Vec<String> { self.raw_content @@ -80,7 +87,9 @@ pub enum LektorResponse { PlaybackStatus(LektorPlaybackStatusResponse), CurrentKara(LektorCurrentKaraResponse), PlaylistSet(LektorPlaylistSetResponse), + IntegerResponse(LektorIntegerResponse), EmptyResponse(LektorEmptyResponse), + KaraInfo(LektorKaraInfoResponse), KaraSet(LektorKaraSetResponse), } @@ -101,7 +110,9 @@ mod private { impl Sealed for LektorPlaybackStatusResponse {} impl Sealed for LektorCurrentKaraResponse {} impl Sealed for LektorPlaylistSetResponse {} + impl Sealed for LektorKaraInfoResponse {} impl Sealed for LektorKaraSetResponse {} + impl Sealed for LektorIntegerResponse {} impl Sealed for LektorEmptyResponse {} } @@ -151,11 +162,21 @@ pub struct LektorCurrentKaraInnerResponse { language: String, } +#[derive(Debug)] +pub struct LektorKaraInfoResponse { + infos: Vec<(String, String)>, +} + #[derive(Debug)] pub struct LektorKaraSetResponse { karas: Vec<String>, } +#[derive(Debug)] +pub struct LektorIntegerResponse { + content: usize, +} + #[derive(Debug)] pub struct LektorCurrentKaraResponse { content: Option<LektorCurrentKaraInnerResponse>, @@ -205,6 +226,12 @@ impl LektorPlaybackStatusResponse { } } +impl LektorIntegerResponse { + pub fn into_inner(self) -> usize { + self.content + } +} + impl LektorKaraSetResponse { pub fn iter(&self) -> &[String] { &self.karas[..] @@ -246,6 +273,29 @@ impl LektorCurrentKaraInnerResponse { } } +impl FromLektorResponse for LektorKaraInfoResponse { + fn from_formated(response: LektorFormatedResponse) -> Result<LektorResponse, String> { + Ok(LektorResponse::KaraInfo(Self { + infos: response.pop_dict(), + })) + } +} + +impl FromLektorResponse for LektorIntegerResponse { + fn from_formated(response: LektorFormatedResponse) -> Result<LektorResponse, String> { + match &response.pop_dict()[..] { + [(_, content)] => { + let content = content.parse::<usize>().map_err(|e| format!("{e}"))?; + Ok(LektorResponse::IntegerResponse(Self { content })) + } + response => Err(format!( + "should have returned only an integer, got {} elements in the response", + response.len(), + )), + } + } +} + impl FromLektorResponse for LektorEmptyResponse { fn from_formated(_: LektorFormatedResponse) -> Result<LektorResponse, String> { Ok(LektorResponse::EmptyResponse(Self {})) diff --git a/src/rust/amadeus-next/lkt-rs/src/main.rs b/src/rust/amadeus-next/lkt-rs/src/main.rs index 7f0ea07132f2971c6c684df3fa06be4972379dee..5173c7986da39c02d929ce12bb312eb285e20c8c 100644 --- a/src/rust/amadeus-next/lkt-rs/src/main.rs +++ b/src/rust/amadeus-next/lkt-rs/src/main.rs @@ -50,7 +50,7 @@ macro_rules! send { }}; } -async fn handle_cmd_queue(_: LktConfig, mut conn: LektorConnexion, cmd: LktQueueCommand) { +async fn handle_cmd_queue(config: LktConfig, mut conn: LektorConnexion, cmd: LktQueueCommand) { match cmd { LktQueueCommand::ShowCurrent => { send!(conn => LektorQuery::CurrentKara; LektorResponse::CurrentKara(kara) => { @@ -62,8 +62,20 @@ async fn handle_cmd_queue(_: LktConfig, mut conn: LektorConnexion, cmd: LktQueue println!("{status:#?}"); }) } - LktQueueCommand::List { range } => todo!(), - LktQueueCommand::ListNext { count } => todo!(), + LktQueueCommand::List { range } => { + send!(conn => LektorQuery::ListQueue(range.clone()); LektorResponse::KaraSet(karas) => { + for (kara, index) in karas.into_iter().zip(range.into_iter()) { println!("{index}: {kara}"); } + }) + } + LktQueueCommand::ListNext { count } => { + let status = send!(conn => LektorQuery::PlaybackStatus; LektorResponse::PlaybackStatus(status) => { status }); + let start = status.song().map(|x| x + 1).unwrap_or(1); + let end = start + count.unwrap_or(config.search.default_queue_count); + let range = start..end; + send!(conn => LektorQuery::ListQueue(range.clone()); LektorResponse::KaraSet(karas) => { + for (kara, index) in karas.into_iter().zip(range.into_iter()) { println!("{index}: {kara}"); } + }) + } LktQueueCommand::Next => send!(conn => LektorQuery::PlayNext; ok), LktQueueCommand::Previous => send!(conn => LektorQuery::PlayPrevious; ok), @@ -91,13 +103,10 @@ async fn handle_cmd_queue(_: LktConfig, mut conn: LektorConnexion, cmd: LktQueue } } LktQueueCommand::Stop => { - match send!(conn => LektorQuery::PlaybackStatus; + if let LektorState::Play(_) | LektorState::Pause(_) = send!(conn => LektorQuery::PlaybackStatus; LektorResponse::PlaybackStatus(status) => { status.state() } ) { - LektorState::Play(_) | LektorState::Pause(_) => { - send!(conn => LektorQuery::Stop; ok) - } - _ => {} + send!(conn => LektorQuery::Stop; ok) } } LktQueueCommand::Play { index: None } => { @@ -140,8 +149,34 @@ async fn handle_cmd_queue(_: LktConfig, mut conn: LektorConnexion, cmd: LktQueue } } -async fn handle_cmd_search(_: LktConfig, _: LektorConnexion, _: LktSearchCommand) { - unimplemented!() +async fn handle_cmd_search(_: LktConfig, mut conn: LektorConnexion, cmd: LktSearchCommand) { + match cmd { + LktSearchCommand::Database { query } => { + send!(conn => LektorQuery::SearchKaraDatabase(query); LektorResponse::KaraSet(karas) => { + for kara in karas { println!("{kara}") } + }) + } + LktSearchCommand::DatabaseCount { query } => { + send!(conn => LektorQuery::CountKaraDatabase(query); LektorResponse::IntegerResponse(count) => { + println!("count: {}", count.into_inner()) + }) + } + LktSearchCommand::Playlist { name, query } => { + send!(conn => LektorQuery::SearchKaraPlaylist(name, query); LektorResponse::KaraSet(karas) => { + for kara in karas { println!("{kara}") } + }) + } + LktSearchCommand::Queue { query } => { + send!(conn => LektorQuery::SearchKaraQueue(query); LektorResponse::KaraSet(karas) => { + for kara in karas { println!("{kara}") } + }) + } + LktSearchCommand::Get { id } => { + send!(conn => LektorQuery::GetKaraInfo(id); LektorResponse::KaraInfo(infos) => { + println!("{infos:#?}") + }) + } + } } async fn handle_cmd_playlist(_: LktConfig, mut conn: LektorConnexion, cmd: LktPlaylistCommand) { diff --git a/src/rust/amadeus-next/lkt-rs/src/parsers.rs b/src/rust/amadeus-next/lkt-rs/src/parsers.rs index f694ffd7a8778ff1a35bc2c851935ebc8715f303..48ce445b03e69857c07ed6fb33f721606b584749 100644 --- a/src/rust/amadeus-next/lkt-rs/src/parsers.rs +++ b/src/rust/amadeus-next/lkt-rs/src/parsers.rs @@ -1,6 +1,5 @@ use clap::{builder::TypedValueParser, error::ErrorKind}; use commons::either; -use std::ops::Range; /// A parser for the [std::ops::Range] structure #[derive(Copy, Clone, Debug, Default)]