Compare commits

...

5 commits

Author SHA1 Message Date
dae598e15c
Use raw strings for mpd commands
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-16 02:03:06 +02:00
9dfa38225f
Throw error when mpd returns an unexpected response 2023-05-16 02:02:21 +02:00
62651ea80b
Make Mpd::connect use Mpd::command 2023-05-16 02:01:26 +02:00
1cf1429753
Add CommandResult::new and CommandResult::new_binary methods 2023-05-16 02:00:43 +02:00
05dddfde6d
Fix error when no track is playing 2023-05-16 01:59:57 +02:00
2 changed files with 41 additions and 34 deletions

View file

@ -53,8 +53,14 @@ async fn get_player(_req: tide::Request<()>) -> tide::Result {
let song = mpd.command("currentsong").await?.into_hashmap();
let status = mpd.command("status").await?.into_hashmap();
let elapsed = status["elapsed"].parse().unwrap_or(0.0);
let duration = status["duration"].parse().unwrap_or(1.0);
let elapsed = status
.get("elapsed")
.and_then(|e| e.parse().ok())
.unwrap_or(0.0);
let duration = status
.get("duration")
.and_then(|e| e.parse().ok())
.unwrap_or(1.0);
let mut template = PlayerTemplate {
song: if song.is_empty() { None } else { Some(&song) },

View file

@ -49,6 +49,20 @@ pub struct CommandResult {
}
impl CommandResult {
pub fn new(properties: Vec<(String, String)>) -> Self {
Self {
properties,
binary: None,
}
}
pub fn new_binary(properties: Vec<(String, String)>, binary: Vec<u8>) -> Self {
Self {
properties,
binary: Some(binary),
}
}
pub fn into_hashmap(self) -> HashMap<String, String> {
self.properties.into_iter().collect()
}
@ -84,28 +98,24 @@ impl Mpd {
}
pub async fn connect() -> anyhow::Result<Self> {
let mut stream = TcpStream::connect(host()).await?;
let mut reader = BufReader::new(stream.clone());
let stream = TcpStream::connect(host()).await?;
let reader = BufReader::new(stream.clone());
let mut this = Self { stream, reader };
// skip OK MPD line
// TODO check if it is indeed OK
let mut buffer = String::new();
reader.read_line(&mut buffer).await?;
this.reader.read_line(&mut buffer).await?;
let password = std::env::var("MPD_PASSWORD").unwrap_or(String::new());
if !password.is_empty() {
let password = Self::escape_str(&password);
let command = format!("password \"{password}\"\n");
stream.write_all(command.as_bytes()).await?;
reader.read_line(&mut buffer).await?;
this.command(&format!(r#"password "{password}""#)).await?;
}
stream.write_all(b"binarylimit 1048576\n").await?;
buffer.clear();
reader.read_line(&mut buffer).await?;
this.command("binarylimit 1048576").await?;
Ok(Self { stream, reader })
Ok(this)
}
async fn read_binary_data(&mut self, size: usize) -> anyhow::Result<Vec<u8>> {
@ -142,21 +152,15 @@ impl Mpd {
if key == "binary" {
let binary = self.read_binary_data(value.parse()?).await?;
break Ok(CommandResult {
properties,
binary: Some(binary),
});
break Ok(CommandResult::new_binary(properties, binary));
}
} else if buffer.starts_with("OK") {
break Ok(CommandResult {
properties,
binary: None,
});
break Ok(CommandResult::new(properties));
} else if buffer.starts_with("ACK") {
break Err(anyhow!(buffer));
} else {
println!("Unexpected MPD response {buffer}");
break Err(anyhow!(buffer));
}
}
}
@ -172,16 +176,10 @@ impl Mpd {
if !binary.is_empty() {
buffer.append(&mut binary);
} else {
return Ok(CommandResult {
properties: result.properties,
binary: Some(buffer),
});
return Ok(CommandResult::new_binary(result.properties, buffer));
}
} else {
return Ok(CommandResult {
properties: result.properties,
binary: None,
});
return Ok(CommandResult::new(result.properties));
}
}
}
@ -200,7 +198,7 @@ impl Mpd {
pub async fn add_pos(&mut self, path: &str, pos: &str) -> anyhow::Result<()> {
let path = Self::escape_str(path);
let pos = Self::escape_str(pos);
self.command(&format!("add \"{path}\" \"{pos}\"")).await?;
self.command(&format!(r#"add "{path}" "{pos}""#)).await?;
Ok(())
}
@ -223,7 +221,9 @@ impl Mpd {
pub async fn albumart(&mut self, path: &str) -> anyhow::Result<Vec<u8>> {
let path = Self::escape_str(path);
let result = self.command_binary(&format!("albumart \"{path}\"")).await?;
let result = self
.command_binary(&format!(r#"albumart "{path}""#))
.await?;
match result.binary {
Some(binary) => Ok(binary),
@ -234,7 +234,7 @@ impl Mpd {
pub async fn readpicture(&mut self, path: &str) -> anyhow::Result<Vec<u8>> {
let path = Self::escape_str(path);
let result = self
.command_binary(&format!("readpicture \"{path}\""))
.command_binary(&format!(r#"readpicture "{path}""#))
.await?;
match result.binary {
@ -252,8 +252,9 @@ impl Mpd {
.unwrap_or("n/a".to_string())
}
let path = Self::escape_str(path);
let result = self
.command(&format!("lsinfo \"{}\"", Self::escape_str(path)))
.command(&format!(r#"lsinfo "{path}""#))
.await?
.into_hashmaps(&["file", "directory", "playlist"]);